Shopify/liquid · error · Liquid::StackLevelError

Nesting too deep

Error message

Nesting too deep

What it means

Liquid raises this StackLevelError (a Liquid::Error subclass, not a SyntaxError) when template nesting depth reaches MAX_DEPTH during parse_body. It guards the recursive block parser against stack exhaustion from deeply or maliciously nested tags, e.g. thousands of nested `{% if %}`s.

Solutions

  1. Flatten the template logic — combine conditions or restructure to reduce nesting levels.
  2. If templates come from users, sanitize/limit them before parse (length, tag counts, include depth).
  3. If recursion is via `{% include %}`, break the include cycle.
  4. Only raise MAX_DEPTH deliberately and with awareness of Ruby stack limits.

Example fix

// before
{% if a %}{% if b %}{% if c %}... (100+ levels) ...{% endif %}{% endif %}{% endif %}
// after
{% if a and b and c %}
  content
{% endif %}
Defensive patterns

Strategy: validation

Validate before calling

def nesting_depth(src)
  cur = max = 0
  src.scan(/{%-?\s*(\w+)/).flatten.each do |t|
    if %w[if for case unless tablerow].include?(t)
      cur += 1; max = [max, cur].max
    elsif t.start_with?('end')
      cur -= 1
    end
  end
  max
end
raise 'too deep' if nesting_depth(src) > 50

Type guard

null

Try / catch

begin
  Liquid::Template.parse(src)
rescue Liquid::StackLevelError => e
  logger.warn("template nesting too deep: #{e.message}")
  nil
end

Prevention

When it happens

Trigger: Parsing a template with more nested block tags than MAX_DEPTH (e.g. >100 nested ifs/fors); recursive includes/includes that reference each other; adversarial user-supplied templates; generated templates with runaway nesting.

Common situations: Accepting user-authored templates (CMS themes, email builders) without depth limits; accidental recursion where a template includes itself; code generators emitting nested conditionals in a loop.

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


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

Appendix: source

Thrown at lib/liquid/block.rb:77

    def block_name
      @tag_name
    end

    def block_delimiter
      @block_delimiter ||= "end#{block_name}"
    end

    private

    # @api public
    def new_body
      parse_context.new_block_body
    end

    # @api public
    def parse_body(body, tokens)
      if parse_context.depth >= MAX_DEPTH
        raise StackLevelError, "Nesting too deep"
      end
      parse_context.depth += 1
      begin
        body.parse(tokens, parse_context) do |end_tag_name, end_tag_params|
          @blank &&= body.blank?

          return false if end_tag_name == block_delimiter
          raise_tag_never_closed(block_name) unless end_tag_name

          # this tag is not registered with the system
          # pass it to the current block for special handling or error reporting
          unknown_tag(end_tag_name, end_tag_params, tokens)
        end
      ensure
        parse_context.depth -= 1
      end

      true

View on GitHub (pinned to 807d45a6b3)