{"record":{"id":"29660d8f4d024075","repo":"Shopify/liquid","slug":"errors-syntax-table-row","errorCode":"errors.syntax.table_row","errorMessage":"options[:locale].t(\"errors.syntax.table_row\")","messagePattern":"options\\[:locale\\]\\.t\\(\"errors\\.syntax\\.table_row\"\\)","errorType":"exception","errorClass":"Liquid::SyntaxError","httpStatus":null,"severity":"error","filePath":"lib/liquid/tags/table_row.rb","lineNumber":78,"sourceCode":"      end\n\n      p.consume(:end_of_string)\n    end\n\n    def strict_parse(markup)\n      lax_parse(markup)\n    end\n\n    def lax_parse(markup)\n      if markup =~ Syntax\n        @variable_name   = Regexp.last_match(1)\n        @collection_name = parse_expression(Regexp.last_match(2))\n        @attributes      = {}\n        markup.scan(TagAttributes) do |key, value|\n          @attributes[key] = parse_expression(value)\n        end\n      else\n        raise SyntaxError, options[:locale].t(\"errors.syntax.table_row\")\n      end\n    end\n\n    def render_to_output_buffer(context, output)\n      (collection = context.evaluate(@collection_name)) || (return '')\n\n      from = @attributes.key?('offset') ? to_integer(context.evaluate(@attributes['offset'])) : 0\n      to = @attributes.key?('limit') ? from + to_integer(context.evaluate(@attributes['limit'])) : nil\n\n      collection = Utils.slice_collection(collection, from, to)\n      length     = collection.length\n\n      cols = @attributes.key?('cols') ? to_integer(context.evaluate(@attributes['cols'])) : length\n\n      output << \"<tr class=\\\"row1\\\">\\n\"\n      context.stack do\n        tablerowloop = Liquid::TablerowloopDrop.new(length, cols)\n        context['tablerowloop'] = tablerowloop","sourceCodeStart":60,"sourceCodeEnd":96,"githubUrl":"https://github.com/Shopify/liquid/blob/807d45a6b3d4568e64e86b375e3702df2c7c860c/lib/liquid/tags/table_row.rb#L60-L96","documentation":"The lax parser of {% tablerow %} matches the markup against its syntax regexp; when there is no match (no variable/collection pair) it raises Liquid::SyntaxError with the localized errors.syntax.table_row message. It indicates the tablerow tag is fundamentally malformed.","triggerScenarios":"{% tablerow %} with no arguments, {% tablerow in items %} missing the variable name, or any markup not matching the tag's SYNTAX regex, reached via strict_parse -> lax_parse.","commonSituations":"Truncated or half-edited templates; generated templates where interpolation of the collection name produced an empty string; copy-paste errors that dropped the loop variable.","solutions":["Provide the full loop syntax: {% tablerow item in collection %}...{% endtablerow %}.","Check that dynamic parts of the tag actually render (empty variable in template source).","Validate templates with Template.parse in CI to catch malformed tags before runtime."],"exampleFix":"// before\n{% tablerow in %}{{ item }}{% endtablerow %}\n// after\n{% tablerow item in items %}{{ item }}{% endtablerow %}","handlingStrategy":"validation","validationCode":"raise 'tablerow needs \"var in collection\"' unless markup =~ /\\A\\s*\\w+\\s+in\\s+\\S+/","typeGuard":"def complete_tablerow_tag?(markup)\n  !markup.to_s.strip.empty? && markup.match?(/\\A\\s*\\w+\\s+in\\s+/)\nend","tryCatchPattern":"begin\n  Liquid::Template.parse(source)\nrescue Liquid::SyntaxError => e\n  raise \"malformed tablerow: #{e.message}\"\nend","preventionTips":["Never emit tablerow tags with interpolated empty segments","Validate generated templates before saving","Keep loop variable and collection present in the tag"],"tags":["liquid","template-syntax","parse-error","tablerow-tag"],"backgroundTag":"missing-required-argument","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"}