Shopify/liquid · error · Liquid::SyntaxError

errors.syntax.if

errors.syntax.if

Error message

options[:locale].t("errors.syntax.if")

What it means

Raised in lax_parse of the {% if %} tag when the markup contains no expression matching the condition Syntax (left operand [operator right operand]). Liquid cannot build the initial Condition, so it raises the generic if-syntax SyntaxError.

Solutions

  1. Provide a complete condition: {% if product.title == 'Foo' %}
  2. Ensure there is a left-hand expression before any operator
  3. Parse templates in CI (Template.parse) to catch malformed if tags early

Example fix

// before
{% if %}...{% endif %}
// after
{% if product.available == true %}...{% endif %}
Defensive patterns

Strategy: validation

Validate before calling

cond = tag_markup.to_s.strip
raise Liquid::SyntaxError, 'if requires a condition expression' if cond.empty?
raise Liquid::SyntaxError, 'if condition malformed' unless cond =~ /\S+(\s+(==|!=|<>|<=|>=|<|>|contains)\s+\S+)?/

Type guard

def valid_if_condition?(markup)
  !markup.to_s.strip.empty?
end

Try / catch

begin
  Liquid::Template.parse(template)
rescue Liquid::SyntaxError => e
  logger.error("Invalid if condition: #{e.message}")
  fallback_template
end

Prevention

When it happens

Trigger: An {% if %} tag with an empty or malformed condition: {% if %}, {% if == x %}, or an if whose expression fails the Syntax regex during lax parsing.

Common situations: Templates where the condition was templated out (e.g. {{ condition }} rendered empty), refactoring that removed the comparison, or accidental whitespace-only if tags.

Related errors


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

Appendix: source

Thrown at lib/liquid/tags/if.rb:90

    def push_block(tag, markup)
      block = if tag == 'else'
        ElseCondition.new
      else
        parse_with_selected_parser(markup)
      end

      @blocks.push(block)
      block.attach(new_body)
    end

    def parse_expression(markup, safe: false)
      Condition.parse_expression(parse_context, markup, safe: safe)
    end

    def lax_parse(markup)
      expressions = markup.scan(ExpressionsAndOperators)
      raise SyntaxError, options[:locale].t("errors.syntax.if") unless expressions.pop =~ Syntax

      condition = Condition.new(parse_expression(Regexp.last_match(1)), Regexp.last_match(2), parse_expression(Regexp.last_match(3)))

      until expressions.empty?
        operator = expressions.pop.to_s.strip

        raise SyntaxError, options[:locale].t("errors.syntax.if") unless expressions.pop.to_s =~ Syntax

        new_condition = Condition.new(parse_expression(Regexp.last_match(1)), Regexp.last_match(2), parse_expression(Regexp.last_match(3)))
        raise SyntaxError, options[:locale].t("errors.syntax.if") unless BOOLEAN_OPERATORS.include?(operator)
        new_condition.send(operator, condition)
        condition = new_condition
      end

      condition
    end

    def strict_parse(markup)

View on GitHub (pinned to 807d45a6b3)