{"record":{"id":"8dcb4816d26b9bd7","repo":"Shopify/liquid","slug":"errors-syntax-tag-never-closed-locale-block-n","errorCode":null,"errorMessage":"errors.syntax.tag_never_closed (locale: \"'{block_name}' tag was never closed\")","messagePattern":"errors\\.syntax\\.tag_never_closed \\(locale: \"'(.+?)' tag was never closed\"\\)","errorType":"exception","errorClass":"Liquid::SyntaxError","httpStatus":null,"severity":"error","filePath":"lib/liquid/block.rb","lineNumber":56,"sourceCode":"      if tag == 'else'\n        raise SyntaxError, parse_context.locale.t(\n          \"errors.syntax.unexpected_else\",\n          block_name: block_name,\n        )\n      elsif tag.start_with?('end')\n        raise SyntaxError, parse_context.locale.t(\n          \"errors.syntax.invalid_delimiter\",\n          tag: tag,\n          block_name: block_name,\n          block_delimiter: block_delimiter,\n        )\n      else\n        raise SyntaxError, parse_context.locale.t(\"errors.syntax.unknown_tag\", tag: tag)\n      end\n    end\n\n    def raise_tag_never_closed(block_name)\n      raise SyntaxError, parse_context.locale.t(\"errors.syntax.tag_never_closed\", block_name: block_name)\n    end\n\n    def block_name\n      @tag_name\n    end\n\n    def block_delimiter\n      @block_delimiter ||= \"end#{block_name}\"\n    end\n\n    private\n\n    # @api public\n    def new_body\n      parse_context.new_block_body\n    end\n\n    # @api public","sourceCodeStart":38,"sourceCodeEnd":74,"githubUrl":"https://github.com/Shopify/liquid/blob/807d45a6b3d4568e64e86b375e3702df2c7c860c/lib/liquid/block.rb#L38-L74","documentation":"Liquid raises this SyntaxError at the end of parsing when a block tag that requires a closing tag (if, for, capture, raw, custom blocks...) was never terminated. parse_body calls raise_tag_never_closed when the token stream ends before the block's delimiter appears, reporting which tag was left open.","triggerScenarios":"Omitting `{% endif %}`, `{% endfor %}`, `{% endcapture %}` etc.; template truncated by a bad include or editor save; an inner tag consuming the outer closer so the outer block reaches EOF; EOF inside a custom block.","commonSituations":"Long templates where the close is far from the open; comment tags hiding the closer; generated templates from string concatenation dropping the last lines; conditional includes that each open blocks but only some close them.","solutions":["Add the missing closing tag named in the error (e.g. append `{% endif %}`).","Re-check nesting by matching each open block to its closer, innermost first.","Beware `{% comment %}`/`{% raw %}` swallowing closers — move them so they don't wrap other blocks' end tags.","For generated templates, validate the assembled string parses before deploying."],"exampleFix":"// before\n{% for item in items %}\n  {{ item.name }}\n// after\n{% for item in items %}\n  {{ item.name }}\n{% endfor %}","handlingStrategy":"validation","validationCode":"OPENS = %w[if for capture case unless raw tablerow comment form paginate]\nstack = []\nsrc.scan(/{%-?\\s*(\\w+)/).flatten.each do |t|\n  if OPENS.include?(t) then stack.push(t)\n  elsif t == 'else' || t == 'elsif' then next\n  elsif t.start_with?('end') then stack.pop\n  end\nend\nputs \"unclosed: #{stack}\" unless stack.empty?","typeGuard":"null","tryCatchPattern":"begin\n  Liquid::Template.parse(src)\nrescue Liquid::SyntaxError => e\n  if e.message =~ /was never closed/\n    logger.error(\"unclosed liquid tag: #{e.message}\")\n    fallback_template\n  else\n    raise\n  end\nend","preventionTips":["Close each block immediately after opening it, then fill in the body.","Don't wrap other blocks' end tags inside comment/raw blocks.","Validate generated/assembled templates before shipping.","Keep templates short; split into partials so pairs stay visible."],"tags":["liquid","template-syntax","unclosed-block","parse-error"],"backgroundTag":"schema-validation-failed","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"}