Shopify/liquid · error · Liquid::SyntaxError
errors.syntax.for_invalid_attribute
errors.syntax.for_invalid_attribute
Error message
options[:locale].t("errors.syntax.for_invalid_attribute") What it means
Raised by strict_parse for {% for %} when an attribute after the collection is neither 'limit' nor 'offset'. Strict mode only permits limit: and offset: parameters, each followed by a colon and an expression.
Solutions
- Replace unsupported keywords with limit: or offset:, e.g. {% for p in products limit: 5 offset: 2 %}
- Ensure a colon follows limit/offset: limit: 10 not limit 10
- Correct spelling of limit/offset attributes
Example fix
// before
{% for p in products by 2 %}...{% endfor %}
// after
{% for p in products limit: 5 offset: 2 %}...{% endfor %} Defensive patterns
Strategy: validation
Validate before calling
attrs = markup.scan(/(\w+)\s*:/).flatten
bad = attrs - %w[limit offset reversed]
raise Liquid::SyntaxError, "invalid for attributes: #{bad.join(',')}" unless bad.empty? Type guard
def valid_for_attributes?(markup)
markup.to_s.scan(/(\w+)\s*:/).flatten.all? { |a| %w[limit offset].include?(a) }
end Try / catch
begin
Liquid::Template.parse(src, error_mode: :strict)
rescue Liquid::SyntaxError => e
logger.error("Invalid for-tag attribute: #{e.message}")
raise
end Prevention
- Only limit: and offset: are valid for-tag parameters in strict mode
- Always use a colon after limit/offset
- Translate other engines' 'by'/'step' pagination to limit/offset before porting templates
When it happens
Trigger: A for tag with a mistyped or unsupported parameter under the strict parser, e.g. {% for p in products by 2 %}, {% for p in products step: 2 %}, or {% for p in products limit 5 %} (missing colon).
Common situations: Porting templates from other template languages that use 'by'/'step' pagination keywords; typos like 'limt:' or 'offest:'; omitting the colon before the value in strict mode.
Related errors
- errors.syntax.for_invalid_in
- errors.syntax.unexpected_outer_tag
- errors.syntax.unknown_tag (locale: 'Unknown tag 'tag'')
- errors.syntax.assign
- errors.syntax.capture
AI-assisted analysis of Shopify/liquid@807d45a6b3 (2026-09-08).
Data as JSON: /api/errors/e360b7c5e7fc73e5.
Report an issue: GitHub.
Appendix: source
Thrown at lib/liquid/tags/for.rb:104
raise SyntaxError, options[:locale].t("errors.syntax.for")
end
end
def strict_parse(markup)
p = @parse_context.new_parser(markup)
@variable_name = p.consume(:id)
raise SyntaxError, options[:locale].t("errors.syntax.for_invalid_in") unless p.id?('in')
collection_name = p.expression
@collection_name = parse_expression(collection_name, safe: true)
@name = "#{@variable_name}-#{collection_name}"
@reversed = p.id?('reversed')
while p.look(:comma) || p.look(:id)
p.consume?(:comma)
unless (attribute = p.id?('limit') || p.id?('offset'))
raise SyntaxError, options[:locale].t("errors.syntax.for_invalid_attribute")
end
p.consume(:colon)
set_attribute(attribute, p.expression, safe: true)
end
p.consume(:end_of_string)
end
private
def strict2_parse(markup)
strict_parse(markup)
end
def collection_segment(context)
offsets = context.registers[:for] ||= {}
from = if @from == :continue
offsets[@name].to_iView on GitHub (pinned to 807d45a6b3)