Shopify/liquid · error · Liquid::SyntaxError

errors.syntax.variable_termination

Error message

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

What it means

Liquid raises this SyntaxError when a `{{ ... }}` output expression is never closed with `}}`. raise_missing_variable_terminator mirrors raise_missing_tag_terminator but for variables, using the VariableEnd regexp (`\}\}`) in the message.

Solutions

  1. Close the variable with `}}` as shown in the error message.
  2. If using another templating layer alongside Liquid, change one layer's delimiters or escape braces.
  3. Balance nested braces/quotes inside the expression.
  4. Validate templates with Liquid::Template.parse in tests before rendering in production.

Example fix

// before
{{ product.title
// after
{{ product.title }}
Defensive patterns

Strategy: validation

Validate before calling

src.each_line do |l|
  opens = l.scan('{{').size
  closes = l.scan('}}').size
  warn "unbalanced braces: #{l}" if opens != closes
end

Type guard

null

Try / catch

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

Prevention

When it happens

Trigger: Writing `{{ user.name` without `}}`; a `}}` consumed by an inner string or nested braces like `{{ a{{b }}`; template truncation; frameworks that treat `{{ }}` as their own syntax (Vue, Jinja conflicts) stripping delimiters.

Common situations: Mixing Liquid with Jinja2/Vue/Handlebars in one file; editors or linters auto-removing braces; heredocs/templated configs where escaping eats a brace; hand-rolled string interpolation.

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/c7ffd7b8de4e9cdc. Report an issue: GitHub.

Appendix: source

Thrown at lib/liquid/block_body.rb:82

        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
      when MemoryError
        raise
      when UndefinedVariable, UndefinedDropMethod, UndefinedFilter
        context.handle_error(exc, line_number)
      else

View on GitHub (pinned to 807d45a6b3)