{"record":{"id":"736215e9a8034cbe","repo":"Shopify/liquid","slug":"errors-syntax-for-invalid-in","errorCode":"errors.syntax.for_invalid_in","errorMessage":"options[:locale].t(\"errors.syntax.for_invalid_in\")","messagePattern":"options\\[:locale\\]\\.t\\(\"errors\\.syntax\\.for_invalid_in\"\\)","errorType":"exception","errorClass":"Liquid::SyntaxError","httpStatus":null,"severity":"error","filePath":"lib/liquid/tags/for.rb","lineNumber":93,"sourceCode":"    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\")\n        end\n        p.consume(:colon)\n        set_attribute(attribute, p.expression, safe: true)\n      end\n      p.consume(:end_of_string)\n    end\n","sourceCodeStart":75,"sourceCodeEnd":111,"githubUrl":"https://github.com/Shopify/liquid/blob/807d45a6b3d4568e64e86b375e3702df2c7c860c/lib/liquid/tags/for.rb#L75-L111","documentation":"Raised by strict_parse for {% for %} when the token immediately after the loop variable is not the keyword 'in'. In strict parsing mode Liquid requires the canonical 'for <var> in <collection>' grammar and refuses lax-style shorthand.","triggerScenarios":"Rendering with the strict parser (error_mode: :strict) and a for tag like {% for item products %}, {% for item of products %}, or {% for 'item' in products %} where the second token isn't the id 'in'.","commonSituations":"Migrating templates from lax to strict error mode (e.g. Shopify theme checks or Rails apps switching error_mode) exposes previously-tolerated typos like 'for x of y'.","solutions":["Use the exact keyword 'in' between variable and collection: {% for item in collection %}","Remove quotes or unusual separators around the loop variable","Audit all for tags when enabling strict mode; use a lint pass to find non-'in' forms"],"exampleFix":"// before\n{% for item of products %}...{% endfor %}\n// after\n{% for item in products %}...{% endfor %}","handlingStrategy":"validation","validationCode":"valid = markup =~ /\\A\\s*[\\w\\-\\\"']+\\s+in\\s+.+\\z/\nraise Liquid::SyntaxError, \"expected 'for x in y'\" unless valid","typeGuard":"def strict_for_ok?(markup)\n  parts = markup.to_s.strip.split(/\\s+/, 3)\n  parts.length >= 3 && parts[1] == 'in'\nend","tryCatchPattern":"begin\n  Liquid::Template.parse(src, error_mode: :strict)\nrescue Liquid::SyntaxError => e\n  logger.error(\"Strict-mode for-tag error: #{e.message}\")\n  raise\nend","preventionTips":["Use the literal keyword 'in' — never 'of', ':', or '=>'","When migrating to strict mode, grep templates for 'for ' tags lacking ' in '","Keep a template test suite that parses with the same error_mode as production"],"tags":["ruby","liquid","strict-mode","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"}