Debugging Shopify Liquid With Claude

Last updated
Expert reviewed
5 min read
Jacques Blom
Jacques Blom
CTO at Fudge.

Key takeaways

  • To debug Shopify Liquid with Claude, paste three things: the template, the exact error, and the object schema. Missing any one of them and Claude guesses.
  • Most Liquid bugs are silent. A nil object prints nothing, so the page renders blank instead of throwing.1
  • Whitespace, filter order, and loop scope cause bugs that look like data problems but are syntax problems.2
  • Claude is strong on template logic and schema JSON. It is weak on live theme state and app-injected code it cannot see.
  • Validate every fix against the Shopify Liquid reference before you push. Do not trust output that cites no source.

To debug Shopify Liquid with Claude, you have to feed it the same context a senior theme developer would ask for. Liquid fails quietly. A missing object does not raise an exception - it renders nothing.1 That makes the “why is this section blank” class of bug hard to reason about from a screenshot alone. This guide covers the common Liquid bugs, the exact context Claude needs, prompt patterns that isolate a bug fast, and where Claude stops being reliable.

For platform setup, see our Shopify AI Toolkit with Claude Code setup guide.


Why you can trust us

Jacques has over 15 years of development experience and has worked with hundreds of Shopify stores. We built Fudge - an AI-native Shopify page builder and store editor with a 5.0 rating and a Built for Shopify badge. We debug Liquid daily, both by hand and with AI assistance.


Why Liquid bugs are hard to spot

Liquid was built to fail safe on a live storefront. That design choice is also what makes it hard to debug.

Only two values are falsy in Liquid: nil and false. Everything else - empty strings, zero, empty arrays - is truthy.1 So a condition you think is guarding against “no data” often passes when the data is empty but present.

A tag or output that returns nil prints nothing to the page and is treated as false.1 There is no stack trace. The section just renders empty, and you are left guessing which object came back nil.

This is the core reason debugging Liquid with Claude works well when done right. You are not asking Claude to catch an exception. You are asking it to reason about which object in a chain resolved to nothing.


The context Claude needs to debug Liquid

The single biggest predictor of a good fix is the context you paste. Give Claude all three of these every time.

1. The template or snippet. Paste the full block, not a fragment. Scope bugs hide in the lines you leave out.

2. The exact error or symptom. “Translation missing: en.products.price” is far more useful than “the price is broken.” If there is no visible error, describe the exact symptom: blank section, wrong count, duplicated block.

3. The object schema. Tell Claude which object you are working with - product, collection, cart - so it validates field names against the real Shopify object rather than inventing them.

A prompt that works:

Here is my section. The price block renders blank on some products
but not others. The object is `product`. What could resolve to nil?

[paste the full section Liquid]

Without the schema, Claude may reference a field that does not exist on that object. Without the full template, it cannot see the loop that changed variable scope.


Common Liquid bugs and how to fix them

Nil and undefined objects

The most common Liquid bug. You access an attribute on an object that is nil, and the whole output disappears.1

The empty state matters too. A deleted resource or a valueless setting returns an empty object, which you should check before reading attributes.1

Before:

<span>{{ product.metafields.custom.subtitle.value }}</span>

If that metafield is unset, the chain resolves to nil and prints nothing. Ask Claude to guard it:

After:

{% if product.metafields.custom.subtitle != blank %}
  <span>{{ product.metafields.custom.subtitle.value }}</span>
{% endif %}

Prompt Claude with: “Which links in this attribute chain can be nil, and how do I guard each one?”

Scope issues inside loops

Variables set inside a for loop, and the forloop object itself, belong to the loop. Every for loop has an associated forloop object with information about the loop.3 Reading it outside the loop gives you nil, not the last value.

If your count is wrong or your “last item” logic misfires, the bug is usually scope. Paste the full loop and ask Claude to trace where each variable is set and read.

Whitespace control

Liquid outputs whitespace where your tags sit. Extra whitespace breaks layouts, inflates HTML, and can even break JSON you build in Liquid.

By including hyphens in your Liquid tag, you can strip whitespace that Liquid generates when rendered. You can add the hyphen to either the opening or closing tag to strip only one side.2

Before:

{% for tag in product.tags %}
  {{ tag }}
{% endfor %}

After:

{%- for tag in product.tags -%}
  {{- tag -}}
{%- endfor -%}

Ask Claude: “This block outputs stray whitespace that breaks my inline layout. Where should the whitespace-control hyphens go?”

Filter chaining order

Multiple filters can be used on one output, and they are applied from left to right.4 Order is not cosmetic. A filter that expects a string will break if an earlier filter already turned the value into an array.

Before:

{{ product.title | split: ' ' | upcase }}

upcase expects a string, but split already returned an array. Reorder, or use the default filter to handle a nil input at the front of the chain.

Ask Claude: “Trace this filter chain left to right. What type does each filter receive and return?”

Skip the Liquid debugging entirely.
Try Fudge for Free

Pagination limits

for loops are capped. You can do a maximum of 50 iterations with a for loop, and beyond that you need the paginate tag.3

The paginate tag splits an array across pages, and page_size must be between 1 and 250.5 It also has a hard ceiling: you can paginate to the 25,000th item and no further, so larger arrays must be filtered before paginating.5

If a collection loop silently stops at 50 products, that is the iteration cap, not a data problem. Ask Claude to wrap the loop in paginate with a valid page_size.

Section and block schema errors

Schema bugs throw at edit time, not render time, which makes them easier to catch.

The {% schema %} must contain only valid JSON. Setting IDs must be unique within each section, and block names and types must be unique within each section. Duplicate IDs, or more than one {% schema %} tag, produce a syntax error when editing theme code.6

Blocks have a limit of 50 per section, lowerable with max_blocks. Static blocks do not count toward that limit.6

Paste the schema block and the exact editor error. Ask Claude to validate the JSON and check ID uniqueness. This is one of Claude’s strongest debugging tasks because the schema is self-contained - no live state required.

For building sections cleanly from the start, see our guide on building a custom section in Shopify.

Missing translation keys

When the t filter cannot find a key in the active locale file, it renders Translation missing: [locale].[key] on the page rather than failing silently.7

Keys use dot notation that maps to the JSON structure, and they must be wrapped in single quotes in Liquid.7 A key like 'products.price' maps to a nested products then price entry in the locale JSON.

Before:

{{ 'products.prise' | t }}

A typo in the key path produces Translation missing: en.products.prise. Paste both the Liquid line and the relevant locale JSON, and Claude will match the key path against the file structure.


Prompt patterns that isolate a bug

Narrow the surface first

Do not paste an entire template and ask “what’s wrong.” Reproduce the bug in the smallest block that still fails, then paste that. A tight block gets a tight answer.

Ask Claude to reason before it edits

Prompt: “Before changing anything, list which objects and variables in this block could be nil or out of scope.” This forces the diagnosis into the open so you can sanity-check it against what you know about the store.

Give it the data shape

If a product has no variants, or a metafield is unset, say so. Claude cannot see your live data. Describing the data shape replaces the guesswork.

One change at a time

Ask for a single fix, test it, then move on. Bundled edits make it hard to tell which change resolved the bug and which introduced a new one.

For more on hand-editing themes safely, see how to edit a Shopify theme.


Validating a fix against the Liquid reference

An AI fix is a hypothesis until you check it. Two habits keep you honest.

Confirm every object and filter exists. If Claude uses a field like product.custom_price, verify it against the Shopify Liquid object reference. Made-up fields resolve to nil and reintroduce the blank-output bug you started with.1

Check filter behavior, not just filter names. Confirm the filter accepts the input type it receives in your chain, since filters apply left to right and each one hands its output to the next.4

The Shopify AI Toolkit can validate generated Liquid against bundled schemas, which shortens this loop. It does not replace a human read of the diff.


Where Claude struggles

Claude is strong on template logic, filter chains, and schema JSON. It has clear blind spots.

Live theme state. Claude cannot see which section is on which template, what a merchant configured in the theme editor, or which app blocks are active. A bug that only appears with a specific setting is invisible to it. You have to describe that state.

App-injected code. Many storefront bugs come from code an app injects at runtime through the theme editor or content_for_header. Claude cannot read code it was never shown. If a bug appears only with an app enabled, that app is a suspect you must surface yourself.

Data-dependent bugs. A section that breaks only on products with no variants, or a nil metafield, is a data-shape problem. Claude cannot query your catalog. It reasons about the data you describe.

This is where an AI system built into the store itself changes the picture. Because Fudge works inside Shopify and understands the store’s brand, products, and context, it operates with the store state that a general coding assistant lacks. For the broader shift toward this way of working, see our take on AI-first Shopify development.


A repeatable debugging loop

  1. Reproduce the bug in the smallest failing block.
  2. Gather the template, the exact error or symptom, and the object schema.
  3. Ask Claude to diagnose before editing - list what could be nil or out of scope.
  4. Apply one fix and test it in isolation.
  5. Validate every object and filter against the Shopify Liquid reference.
  6. Push as unpublished first, never straight to the live theme.

That loop turns Liquid’s silent-failure model from a liability into a checklist.

For deeper work on custom logic, see how to add custom Liquid logic in Shopify.


Summary

Debugging Shopify Liquid with Claude comes down to context and validation. Paste the template, the error, and the object schema, and Claude can trace nil chains, loop scope, filter order, and schema JSON with real accuracy. Keep it away from the things it cannot see - live theme state, app-injected code, and your catalog data. Validate every fix against the Liquid reference before it ships.

If you would rather not debug Liquid at all, that is the case for editing your store through an AI store editor that already knows your store.


FAQ

Why does my Shopify section render blank with no error?

Liquid fails silently. A tag or output that returns nil prints nothing and is treated as false, so there is no stack trace - the section just renders empty. The usual cause is an object or attribute chain that resolved to nil. Paste the full section and the object name to Claude and ask which links in the chain could be nil.

How do I give Claude enough context to debug Liquid?

Paste three things every time: the full template or snippet, the exact error or symptom (for example "Translation missing: en.products.price"), and the object you are working with (product, collection, cart). Without the object schema, Claude may reference fields that do not exist. Without the full template, it cannot see the loop that changed variable scope.

Why does my Liquid for loop stop at 50 items?

That is the built-in cap. A for loop does a maximum of 50 iterations. To go further you wrap the loop in the paginate tag, where page_size must be between 1 and 250, and you can paginate to the 25,000th item and no further. If a collection loop silently truncates, it is the iteration limit, not a data problem.

What does "Translation missing" mean in Shopify Liquid?

The t filter could not find your key in the active locale file, so it renders "Translation missing: [locale].[key]" on the page instead of failing silently. It is usually a typo in the dot-notation key path or a key absent from the locale JSON. Keys must be wrapped in single quotes. Paste both the Liquid line and the locale JSON so Claude can match the key path.

Can Claude see my live Shopify theme and app code?

No. Claude only sees code you paste. It cannot see which section is on which template, what a merchant set in the theme editor, or code an app injects at runtime through content_for_header. If a bug appears only with a specific setting or app enabled, you have to describe that state - it is invisible to a general coding assistant.

How do I stop Claude from inventing Liquid fields that do not exist?

Validate every object and filter it uses against the Shopify Liquid reference before you push. Made-up fields like product.custom_price resolve to nil and reintroduce the blank-output bug. Ask Claude to cite the object it is using, and check that filters accept the input type they receive, since filters apply left to right.

Why does reordering my Liquid filters change the output?

Filters apply from left to right, and each hands its output to the next. If a filter expects a string but an earlier filter already returned an array, it breaks. For example, split before upcase gives upcase an array instead of a string. Ask Claude to trace the chain and note the type each filter receives and returns.

Jacques's signature
Edit your Shopify storefront without debugging Liquid.

Footnotes

  1. Shopify Liquid basics - nil, empty, and truthy/falsy behavior. https://shopify.dev/docs/api/liquid/basics 2 3 4 5 6 7

  2. Shopify Liquid basics - whitespace control with hyphens. https://shopify.dev/docs/api/liquid/basics 2

  3. Shopify Liquid for tag - 50-iteration limit and forloop object. https://shopify.dev/docs/api/liquid/tags/for 2

  4. Shopify Liquid filters - pipe syntax and left-to-right chaining. https://shopify.dev/docs/api/liquid/filters 2

  5. Shopify Liquid paginate tag - page_size range and 25,000-item ceiling. https://shopify.dev/docs/api/liquid/tags/paginate 2

  6. Shopify section schema - valid JSON, unique IDs, and the 50-block limit. https://shopify.dev/docs/storefronts/themes/architecture/sections/section-schema 2

  7. Shopify translate (t) filter - “Translation missing” behavior and key mapping. https://shopify.dev/docs/api/liquid/filters/translate 2

You might also be interested in

How to Use Shopify Sidekick (2026)
How to use Shopify Sidekick for store management. Covers setup, effective commands, current limitations, and tips to get useful results.
Claude Prompts for Shopify: A Library of 40+ Prompts
40+ copy-paste Claude prompts for Shopify operators: Liquid and theme dev, PDP copy, SEO, metafields, CRO, analytics, debugging, and migration.
AI for Shopify SEO: Meta Titles, Descriptions and Schema
AI Shopify SEO workflow using Claude to draft meta titles and descriptions at scale and generate Product, FAQ, and BreadcrumbList JSON-LD.