Add UnsupportedFilterArguments check#1248
Merged
Merged
Conversation
822c759 to
7eea0d2
Compare
mbarak
approved these changes
Jun 27, 2026
… specs Co-authored-by: Pi AI (anthropic/claude-opus-4-8) <pi-ai@users.noreply.github.com>
Co-authored-by: Pi AI (anthropic/claude-opus-4-8) <pi-ai@users.noreply.github.com>
NathanPJF
commented
Jun 27, 2026
NathanPJF
left a comment
Contributor
Author
There was a problem hiding this comment.
Thanks for the review @mbarak . I decided to rename the check now to UnsupportedFilterArguments since it's covering more than just render now. That makes it easier to expand in the future if need be.
I also noticed that none of the other checks started with "No", so I chose something that feels closer to the existing patterns.
Going to update the Dev Docs PR now.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What & why
Filters aren't supported on values passed as arguments to render/include tags — but today theme-check says nothing when you write one. The value is silently passed through unchanged, so this:
{% render 'paragraph', text: 'Hello,' | append: ' World!' %}renders
Hello,(notHello, World!) with zero feedback making it hard to debug or notice unexpected markup in production.Examples of what happens in a production Shopify store
Code used
Real world use-case:
We were creating unique IDs to pass into snippets, but making them unique inline at the render tag. The result was all the
idvalues got rendered as the same value. 😬Root cause: theme-check's parser is tolerant — when a tag doesn't match the strict grammar, it doesn't error, it just stores the tag as a raw text blob and moves on. The grammar intentionally doesn't allow filters on render arguments, so
{% render 'foo', x: 'a' | append: 'b' %}fails the strict parse and falls back to a generic LiquidTag holding the raw string, instead of becoming the structured RenderMarkup node a valid render produces. No error is raised, which is the silent failure. It also means existing render checks (which run on RenderMarkup nodes) never see it — so this check runs on the generic LiquidTag fallback and detects the leftover filter pipe directly.Approach
A LiquidTag-visitor check that keys off exactly that fallback:
|not inside a quoted string literal (sosep: 'a|b'doesn't false-positive).This throws a clean, hard error. The shared grammar is untouched.
Decision Severity is
ERRORand the check is recommended (on by default), since the failure is silent and produces incorrect output. We could change this toWARNING, but I think thatERRORis appropriate since we are protecting against unexpected outputs that can affect the site's functionality.Limitation: the guard is a heuristic on raw markup ("render/include that failed strict parse + contains an unquoted pipe"), because the AST node genuinely doesn't exist for malformed renders. This means no per-argument
precision (e.g. "filter on param2"). Acceptable given an unquoted
|inside a render tag is essentially always a filter attempt.Changes
Testing
My test cases:
6 new unit specs (render filter, include filter, no-filter, 'a|b' no false positive, plain render, nested) — all green; full theme-check-common suite (959 tests) passes.
I ran the local build against my test file. 3 real offenses, 0 false positives.
Output:
Co-Authored by AI
Before you deploy
Check changes
changesetpnpm buildand committed the updated configuration filestheme-app-extension.ymlconfigPublic API changes, new features
changeset