Shopify/liquid · error · Liquid::SyntaxError
errors.syntax.for_invalid_in
errors.syntax.for_invalid_in
Error message
options[:locale].t("errors.syntax.for_invalid_in") What it means
The strict2 parser of the {% tablerow %} tag requires the literal keyword 'in' between the loop variable and the collection. If the parser cannot consume 'in' after the variable name, it raises Liquid::SyntaxError with the localized errors.syntax.for_invalid_in message.
Solutions
- Add the missing 'in' keyword: {% tablerow item in items %}...{% endtablerow %}.
- Fix typos in the keyword ('in' exactly, lowercase).
- Run Template.parse on the template in tests to catch the offending tag and line before rendering.
Example fix
// before
{% tablerow product products %}{{ product.title }}{% endtablerow %}
// after
{% tablerow product in products %}{{ product.title }}{% endtablerow %} Defensive patterns
Strategy: validation
Validate before calling
raise 'tablerow requires: {% tablerow var in collection %}' unless markup =~ /\A\s*\w+\s+in\s+/ Type guard
def valid_tablerow_markup?(markup) markup =~ /\A\s*[a-zA-Z_]\w*\s+in\s+.+\z/ end
Try / catch
begin
Liquid::Template.parse(source)
rescue Liquid::SyntaxError => e
raise "tablerow markup error: #{e.message}"
end Prevention
- Always include the 'in' keyword between variable and collection
- Run template parse tests in CI
- Avoid hand-editing tablerow tags without re-validating
When it happens
Trigger: Markup like {% tablerow item items %} (missing 'in'), {% tablerow item in2 items %} (typo), or a parser in strict2 mode being fed a tablerow tag lacking the 'in' keyword.
Common situations: Hand-written templates missing 'in'; migrations from lenient parsers where malformed tags used to be tolerated; typos such as 'on' or 'inn'.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- errors.syntax.table_row
- errors.syntax.unexpected_else (locale: Unexpected 'else'…
- errors.syntax.invalid_delimiter
- errors.syntax.unknown_tag (locale: 'Unknown tag 'tag'')
- errors.syntax.tag_never_closed
AI-assisted analysis of Shopify/liquid@807d45a6b3 (2026-09-08).
Data as JSON: /api/errors/fa9c199c68a8eb0f.
Report an issue: GitHub.
Appendix: source
Thrown at lib/liquid/tags/table_row.rb:43
# @liquid_optional_param range [untyped] A custom numeric range to iterate over.
class TableRow < Block
Syntax = /(\w+)\s+in\s+(#{QuotedFragment}+)/o
ALLOWED_ATTRIBUTES = ['cols', 'limit', 'offset', 'range'].freeze
attr_reader :variable_name, :collection_name, :attributes
def initialize(tag_name, markup, options)
super
parse_with_selected_parser(markup)
end
def strict2_parse(markup)
p = @parse_context.new_parser(markup)
@variable_name = p.consume(:id)
unless p.id?("in")
raise SyntaxError, options[:locale].t("errors.syntax.for_invalid_in")
end
@collection_name = safe_parse_expression(p)
p.consume?(:comma)
@attributes = {}
while p.look(:id)
key = p.consume
unless ALLOWED_ATTRIBUTES.include?(key)
raise SyntaxError, options[:locale].t("errors.syntax.table_row_invalid_attribute", attribute: key)
end
p.consume(:colon)
@attributes[key] = safe_parse_expression(p)
p.consume?(:comma)
end
View on GitHub (pinned to 807d45a6b3)