TLDR: Liquid won't let you run a filter inside an {% if %} condition. Assign the result to a variable first, then compare. Simple — except your LLM will get it wrong every single time.

The Build

I'm running a Shopify theme cloning automation — a tool that reverse-engineers a third-party Shopify landing page into an ecommerce business-branded Liquid theme — cloning a health supplement brand's HSA/FSA landing page onto an ecommerce business's health supplement product.

The page had a selling plan selector.

Selling plan IDs come off the selling_plan_allocation object as integers. The section setting that stores the preselected plan is a string. You can't compare them directly — they're different types.

The "obvious" fix is to coerce the ID to a string inline, right in the condition.

What I Wrote (and What Blew Up)

{% if alloc.selling_plan.id | append: '' == section.settings.default_selling_plan_id %}
  checked
{% endif %}

Seems reasonable. append: '' coerces an integer to a string. And it works great… in an output tag.

Inside {% if %}, Liquid's parser hits the pipe and panics.

Liquid syntax error: Expected end_of_string but found pipe.

The section fails to upload. The template breaks. Full debug-and-repush cycle. Not fun.

The Fix That Actually Works

Two lines instead of one.

{% assign sc_plan_str = alloc.selling_plan.id | append: '' %}
{% if sc_plan_str == section.settings.default_selling_plan_id %}checked{% endif %}

That's it. Assign the coerced value first, then compare.

Works perfectly. 529236061 matched its string counterpart, the selling plan pre-selected on load, 12/12 sections clean on push.

Why This Matters Beyond My Weird Build

Here's the part that stuck with me.

This isn't a one-time gotcha. My LLM generated the broken pattern by default. Every time. Because value | filter == "foo" looks valid — it's how you'd write it in Twig, in Jinja, in a dozen other template languages. The "natural" translation from English to Liquid is wrong.

That means any pipeline where an LLM writes Liquid — mine, yours, anyone's — will produce this bug silently, at scale, until you add post-processing to catch it.

The commit that fixed this wasn't just a one-off hand edit. It became a validation rule baked into a post-processing function in the theme generation pipeline, running over every generated section before it touches the theme.

The lesson isn't just "assign before compare."

The lesson is: when your LLM will predictably generate the same wrong thing, fix the pipeline, not the output.

P.S. This was one of five Shopify validation quirks that hit me in a single build. The 25-character schema name cap and the two-phase push order (sections first, template second) are the other two worth remembering — but the assign gotcha is the sneakiest because the error message gives you almost nothing to go on.