How to Debug Shopify Liquid: A Complete Guide
Source: Dev.to
Why Is Liquid Hard to Debug?
Liquid is a templating language, not a programming language. It runs server‑side on Shopify’s infrastructure, which means:
| Limitation | Explanation |
|---|---|
| No browser DevTools | You can’t inspect Liquid like you inspect JavaScript. |
No console.log | There’s no native way to print debug output. |
| Silent failures | Many errors render as empty strings instead of error messages. |
| No stack traces | When something breaks, you don’t know where. |
| Server‑rendered | Every change requires a page refresh to test. |
These factors make debugging a slow, frustrating process of trial and error.
Method 1: The json Filter
The most common debugging technique is outputting objects as JSON.
{{ product | json }}
Renders the entire product object as a JSON string in your HTML.
You can then:
- View page source or inspect the element.
- Copy the JSON output.
- Paste into a JSON formatter to read it.
Limitations
- Clutters your HTML output.
- Easy to forget and leave in production code.
- Requires refreshing the page for every change.
- Large objects are hard to navigate.
- No syntax highlighting or search.
Better: Wrap in a <script> Tag
<script>
console.log('Product:', {{ product | json }});
</script>
Now you can view the formatted data in the browser DevTools console.
Method 2: Shopify Theme Check
Theme Check is Shopify’s official linter for Liquid. It catches common errors before you deploy.
Installation
# Via Shopify CLI
shopify theme check
# Or standalone
gem install theme-check
theme-check
What It Catches
- Undefined objects and variables.
- Deprecated tags and filters.
- Missing template files.
- Performance issues (e.g., too many API calls).
- Translation key errors.
Limitations
- Static analysis only — doesn’t catch runtime errors.
- Can’t inspect actual data values.
- Runs in the terminal, not in the browser.
- No live debugging.
Method 3: Shopify’s Built‑in Error Messages
Liquid surfaces some errors directly in the HTML output. Look for messages such as:
Liquid error: undefined method 'title' for nil:NilClass
Liquid syntax error: Unknown tag 'endfor'
How to Find Them
- View page source (
Cmd+U/Ctrl+U). - Search for “Liquid error” or “Liquid syntax”.
- The error message usually indicates the file and line number.
Common Error Patterns
| Error | Cause | Fix |
|---|---|---|
undefined method for nil:NilClass | Accessing a property on a null object | Add {% if object %} checks |
Unknown tag | Typo in tag name | Verify spelling (endif not end if) |
Could not find snippet | Missing snippet file | Create the file or fix the path |
Invalid JSON | Malformed JSON in section schema | Validate your JSON syntax |
Method 4: Preview Inspector (Theme Editor)
Shopify’s theme customizer includes a basic inspector:
- Open the theme customizer.
- Click on a section.
- View the available settings and blocks.
Limitations
- Only shows section settings, not Liquid objects.
- Can’t inspect product, cart, or collection data.
- No expression evaluation.
- No error detection.
Method 5: Browser DevTools (for JavaScript)
If your Liquid outputs data for JavaScript consumption, you can debug the JavaScript side.
<script>
window.productData = {{ product | json }};
</script>
Then, in the browser console:
console.log(productData.title);
console.log(productData.variants[0].price);
Limitations
- Only works for data you explicitly expose.
- Can’t access Liquid‑only objects like
templateorrequest. - Requires modifying your code to expose data.
Method 6: In‑Browser Liquid DevTools
The most comprehensive solution is using dedicated developer tools that run in the browser.
Shopify Theme Devtools is an open‑source panel that provides:
Objects Inspector
Browse all Liquid objects in a collapsible tree view:
shop– Store settings, currency, localeproduct– Current product with variants, images, metafieldscollection– Collection data with productscart– Live cart state with items and attributescustomer– Logged‑in customer datatemplate– Current template name and directoryrequest– Page URL, host, path
Click any property to copy its Liquid path.
Live Expression Evaluator
Test Liquid expressions without refreshing:
> product.title
"Classic Cotton T-Shirt"
> product.price | money
"$29.99"
> cart.items | size
3
> product.variants | first | json
{"id":12345,"title":"Small / Blue",...}
Supports 50+ Liquid filters, including money, money_with_currency, img_url, asset_url, and more.
Automatic Error Detection
Scans the page for common Liquid issues:
| Error Type | Example |
|---|---|
| Liquid errors | Liquid error: undefined method 'size' |
| Syntax errors | Liquid syntax error: Unknown tag 'endif' |
| Drop object leaks | # |
| Missing snippets | Could not find snippet 'missing-file' |
| Schema errors | Invalid JSON in section schema |
Putting It All Together
- Start with the
jsonfilter for quick data inspection. - Run Theme Check locally to catch static issues.
- Watch for built‑in Liquid error messages in the rendered HTML.
- Use the Preview Inspector for section‑level debugging.
- Expose data to JavaScript when you need to debug client‑side logic.
- Leverage Shopify Theme Devtools for a full‑featured, in‑browser debugging experience.
By combining these methods, you can dramatically reduce the time spent hunting down Liquid bugs and ship more reliable Shopify themes. Happy debugging!
Cart Debugging
- View live cart state with all items and properties
- Adjust quantities without leaving the panel
- Save and restore cart snapshots
- View cart history with timestamps
Installation
npx shopify-theme-devtools init --inject
Then press Cmd+Shift+D (Mac) or Ctrl+Shift+D (Windows) to open.
Only loads on development themes — safe to commit to your repository.
Common Liquid Errors and Solutions
1. “undefined method for nil:NilClass”
Cause: Accessing a property on an object that doesn’t exist.
{{ product.title }}
Fix: Always check if the object exists first.
{% if product %}
{{ product.title }}
{% endif %}
2. “Unknown tag”
Cause: Typo in a Liquid tag name.
{% end if %}
{% endif %}
3. Drop object leak (#ProductDrop:0x...)
Cause: Outputting a Liquid object without the json filter.
// Bad
const product = {{ product }};
// Good
const product = {{ product | json }};
4. “Could not find snippet”
Cause: Rendering a snippet that doesn’t exist.
{% render 'non-existent-snippet' %}
Fix: Check the snippet filename and ensure it’s in the snippets/ folder.
5. Empty output (no error)
Cause: Variable is nil or empty; Liquid silently outputs nothing.
Debug: Use the json filter to see the actual value.
{{ my_variable | json }}
6. “Invalid JSON in schema”
Cause: Section schema has malformed JSON.
{% schema %}
{
"name": "My Section",
"settings": [
{
"type": "text",
"id": "title"
"label": "Title"
}
]
}
{% endschema %}
Fix: Validate your JSON at a JSON validator.
7. Incorrect money formatting
Cause: Using raw price values without the money filter.
{{ product.price }}
{{ product.price | money }}
8. Array index out of bounds
Cause: Accessing an array index that doesn’t exist.
{{ product.images[2].src }}
Fix: Check array size first.
{% if product.images.size > 2 %}
{{ product.images[2].src }}
{% endif %}
Debugging Workflow: A Step‑by‑Step Process
When you encounter an issue, follow this process:
Step 1: Check for visible errors
Search your page source for “Liquid error” or “Liquid syntax error”.
Step 2: Isolate the problem
Comment out sections of code until the error disappears:
{% comment %}
{{ potentially_broken_code }}
{% endcomment %}
Step 3: Inspect the data
Use JSON output or a devtools panel to see what data is actually available:
{{ product | json }}
Step 4: Verify object existence
Add existence checks around the problematic code:
{% if product %}
{% if product.metafields.custom.size > 0 %}
{{ product.metafields.custom | json }}
{% else %}
<!-- No custom metafields -->
{% endif %}
{% else %}
<!-- No product -->
{% endif %}
Step 5: Test expressions incrementally
Break complex expressions into smaller parts:
{{ product.metafields.custom.c }}