{"record":{"id":"61665208b6920df0","repo":"Shopify/liquid","slug":"errors-syntax-for","errorCode":"errors.syntax.for","errorMessage":"options[:locale].t(\"errors.syntax.for\")","messagePattern":"options\\[:locale\\]\\.t\\(\"errors\\.syntax\\.for\"\\)","errorType":"exception","errorClass":"Liquid::SyntaxError","httpStatus":null,"severity":"error","filePath":"lib/liquid/tags/for.rb","lineNumber":86,"sourceCode":"      end\n\n      output\n    end\n\n    protected\n\n    def lax_parse(markup)\n      if markup =~ Syntax\n        @variable_name   = Regexp.last_match(1)\n        collection_name  = Regexp.last_match(2)\n        @reversed        = !!Regexp.last_match(3)\n        @name            = \"#{@variable_name}-#{collection_name}\"\n        @collection_name = parse_expression(collection_name)\n        markup.scan(TagAttributes) do |key, value|\n          set_attribute(key, value)\n        end\n      else\n        raise SyntaxError, options[:locale].t(\"errors.syntax.for\")\n      end\n    end\n\n    def strict_parse(markup)\n      p = @parse_context.new_parser(markup)\n      @variable_name = p.consume(:id)\n      raise SyntaxError, options[:locale].t(\"errors.syntax.for_invalid_in\") unless p.id?('in')\n\n      collection_name  = p.expression\n      @collection_name = parse_expression(collection_name, safe: true)\n\n      @name     = \"#{@variable_name}-#{collection_name}\"\n      @reversed = p.id?('reversed')\n\n      while p.look(:comma) || p.look(:id)\n        p.consume?(:comma)\n        unless (attribute = p.id?('limit') || p.id?('offset'))\n          raise SyntaxError, options[:locale].t(\"errors.syntax.for_invalid_attribute\")","sourceCodeStart":68,"sourceCodeEnd":104,"githubUrl":"https://github.com/Shopify/liquid/blob/807d45a6b3d4568e64e86b375e3702df2c7c860c/lib/liquid/tags/for.rb#L68-L104","documentation":"Liquid raises this SyntaxError from the {% for %} tag's lax_parse when the tag markup doesn't match the required 'for <var> in <collection>' shape. The lax parser scans the markup with TagAttributes and, on falling into the else branch, cannot find a valid variable/collection pair. It signals that the for-loop declaration itself is malformed (not the loop body).","triggerScenarios":"A {% for %} tag whose markup lacks the 'in' structure, e.g. {% for %}, {% for item %}, or {% for in items %}; any for tag failing lax mode syntax parsing in parse.liquid templates rendered with the default (lax) parser.","commonSituations":"Hand-edited templates with a deleted variable or collection expression; template strings built dynamically via interpolation where a variable came out empty; copy-paste from docs that dropped the 'item in collection' part.","solutions":["Fix the for tag to the form {% for item in collection %} with a variable name and a collection expression","If the collection may be empty/nil, ensure the expression is still syntactically present (e.g. {% for item in products %}), guarding emptiness inside the loop","Run the template through Template.parse in a test to catch the SyntaxError at load time instead of render time"],"exampleFix":"// before\n{% for %} ... {% endfor %}\n// after\n{% for item in products %} ... {% endfor %}","handlingStrategy":"validation","validationCode":"markup = tag_markup # the text between {% for and %}\nvalid = markup =~ /\\A\\s*[\\w\\-]+\\s+in\\s+.+\\s*\\z/\nraise Liquid::SyntaxError, 'for tag must be: for <var> in <collection>' unless valid","typeGuard":"def valid_for_tag?(markup)\n  !!(markup.to_s =~ /\\A\\s*[\\w\\-\\\"']+\\s+in\\s+\\S/)\nend","tryCatchPattern":"begin\n  Liquid::Template.parse(template)\nrescue Liquid::SyntaxError => e\n  logger.error(\"Liquid for-tag syntax: #{e.message}\")\n  fallback_template\nend","preventionTips":["Always write for tags as {% for item in collection %}","Parse all templates at deploy time (Template.parse) so syntax errors surface before render","Lint templates in CI with theme-check or similar"],"tags":["ruby","liquid","template-syntax"],"backgroundTag":"template-syntax-error","analyzedSha":"807d45a6b3d4568e64e86b375e3702df2c7c860c","analyzedAt":"2026-09-08T11:31:38.917Z","contentChangedAt":"2026-09-08T11:31:38.917Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}