Shopify/liquid · error · Liquid::SyntaxError
# is not a valid expression
Error message
#{token} is not a valid expression What it means
Liquid::Parser#expression raises Liquid::SyntaxError when the current token cannot start any recognized expression (identifier, string, number, range, etc.). The unexpected token text is embedded in the message.
Solutions
- Fix the template so a valid expression precedes operators/delimiters (e.g. add the missing value before | )
- Parse templates with Liquid::Template.parse in CI to catch this early
- Remove stray tokens (commas, pipes, colons) that aren't part of a complete expression
Example fix
<!-- before -->
{{ | upcase }}
<!-- after -->
{{ title | upcase }} Defensive patterns
Strategy: validation
Validate before calling
def expression_starts_valid?(expr) expr !~ /^\s*[|,:.)]/ end
Try / catch
begin Liquid::Template.parse(tpl) rescue Liquid::SyntaxError => e raise unless e.message =~ /is not a valid expression/ # log template location and offending token end
Prevention
- Ensure every filter/argument has a preceding operand
- Lint templates before deploying
- Avoid string-interpolated template generation without tests
When it happens
Trigger: Encountering tokens like an unexpected operator (|, ,, :), closing delimiter, or keyword where an operand is required, e.g. {{ | upcase }} or {% assign = 5 %}.
Common situations: Filters written without a preceding value; stray commas or colons in tag arguments; half-edited templates; malformed range literals like (..5).
Related errors
- Expected # but found #
- unsafe parse_expression cannot be used in strict2 mode
- Bare bracket access is not allowed. Use #
- Invalid expression type '#
- Memory limits exceeded
AI-assisted analysis of Shopify/liquid@807d45a6b3 (2026-09-08).
Data as JSON: /api/errors/188ff7ed6936c19c.
Report an issue: GitHub.
Appendix: source
Thrown at lib/liquid/parser.rb:74
when :open_square
if @reject_bare_brackets
raise SyntaxError, "Bare bracket access is not allowed. Use #{Expression::SELF}['...'] instead"
end
str = consume.dup
str << expression
str << consume(:close_square)
str << variable_lookups
when :string, :number
consume
when :open_round
consume
first = expression
consume(:dotdot)
last = expression
consume(:close_round)
"(#{first}..#{last})"
else
raise SyntaxError, "#{token} is not a valid expression"
end
end
def argument
str = +""
# might be a keyword argument (identifier: expression)
if look(:id) && look(:colon, 1)
str << consume << consume << ' '
end
str << expression
str
end
def variable_lookups
str = +""
loop do
if look(:open_square)View on GitHub (pinned to 807d45a6b3)