Shopify/liquid · error · Liquid::SyntaxError

errors.syntax.tag_termination

Error message

errors.syntax.tag_termination (locale: "Tag '{token}' was not properly terminated with regexp: {tag_end}")

What it means

Liquid raises this SyntaxError when a `{% ... %}` tag is never closed with the tag-end delimiter (`%}`), detected during block body parsing. raise_missing_tag_terminator is invoked when the scanner reaches EOF (or an unexpected token boundary) while still inside a tag, showing the raw token and the expected terminator regexp.

Solutions

  1. Add the missing `%}` terminator to the tag shown in the error.
  2. Check that quotes inside the tag are balanced — an unclosed string can hide the `%}`.
  3. Verify the file wasn't truncated or mangled by a build/minify step.
  4. Use an editor with Liquid syntax highlighting to spot unterminated tags early.

Example fix

// before
{% assign title = page.title }
// after
{% assign title = page.title %}
Defensive patterns

Strategy: validation

Validate before calling

src.scan(/{%(?!%).*?[^%]\z/) # sanity: ensure every `{%` on a line has a following `%}`
src.each_line { |l| warn "unterminated tag: #{l}" if l.include?('{%') && !l.include?('%}') }

Type guard

null

Try / catch

begin
  Liquid::Template.parse(src)
rescue Liquid::SyntaxError => e
  if e.message.include?('was not properly terminated')
    logger.error("unterminated liquid tag: #{e.message}")
    fallback_template
  else
    raise
  end
end

Prevention

When it happens

Trigger: Writing `{% if x }` or `{% assign y = 1` (missing `%}`); an editor stripping `%}`; unquoted strings containing characters that swallow the terminator like `{% assign x = "a%}" ...` mis-nesting; truncated template files.

Common situations: Hand-writing templates in editors without Liquid syntax highlighting; minifiers or HTML sanitizers mangling `%}`; copy/paste losing characters; templates stored in YAML/JSON where `}` escaping goes wrong.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


AI-assisted analysis of Shopify/liquid@807d45a6b3 (2026-09-08). Data as JSON: /api/errors/5e24d893ccae26ad. Report an issue: GitHub.

Appendix: source

Thrown at lib/liquid/block_body.rb:77

          end
          new_tag = tag.parse(tag_name, markup, tokenizer, parse_context)
          @blank &&= new_tag.blank?
          @nodelist << new_tag
        end
        parse_context.line_number = tokenizer.line_number
      end

      yield nil, nil
    end

    # @api private
    def self.unknown_tag_in_liquid_tag(tag, parse_context)
      Block.raise_unknown_tag(tag, 'liquid', '%}', parse_context)
    end

    # @api private
    def self.raise_missing_tag_terminator(token, parse_context)
      raise SyntaxError, parse_context.locale.t("errors.syntax.tag_termination", token: token, tag_end: TagEnd.inspect)
    end

    # @api private
    def self.raise_missing_variable_terminator(token, parse_context)
      raise SyntaxError, parse_context.locale.t("errors.syntax.variable_termination", token: token, tag_end: VariableEnd.inspect)
    end

    # @api private
    def self.render_node(context, output, node)
      node.render_to_output_buffer(context, output)
    rescue => exc
      blank_tag = !node.instance_of?(Variable) && node.blank?
      rescue_render_node(context, output, node.line_number, exc, blank_tag)
    end

    # @api private
    def self.rescue_render_node(context, output, line_number, exc, blank_tag)
      case exc

View on GitHub (pinned to 807d45a6b3)