Skip to content

Bug: {% liquid liquid %} raises raw NoMethodError when line numbers are disabled #2101

Description

@Nuhiat-Arefin

Version

  • liquid 5.12.0
  • Ruby 4.0.5
  • Default parse options, where line_numbers is not enabled

Steps to reproduce

require "liquid"

Liquid::Template.parse("{% liquid liquid %}")

Actual behavior

Parsing raises a raw NoMethodError:

NoMethodError: undefined method '-' for nil
  .../liquid-5.12.0/lib/liquid/block_body.rb:51:in `Liquid::BlockBody#parse_for_liquid_tag'

This happens in both :strict and :lax error modes.

Because the exception is not a Liquid::Error, application code that wraps parsing with rescue Liquid::Error will not catch it.

Expected behavior

The template should parse without crashing and render as an empty string.

This is already what happens when line numbers are enabled:

Liquid::Template.parse("{% liquid liquid %}", line_numbers: true).render!
# => ""

For comparison, the same template is accepted as a no-op by other major Liquid implementations:

  • LiquidJS 10.27.0 renders ""
  • python-liquid 2.2.1 renders ""

Root cause

The crash appears to come from lib/liquid/block_body.rb in parse_for_liquid_tag:

if tag_name == 'liquid'
  parse_context.line_number -= 1
  next parse_liquid_tag(markup, parse_context)
end

When line numbers are not tracked, parse_context.line_number is nil. A nested {% liquid %} line therefore executes:

nil -= 1

which raises:

NoMethodError: undefined method '-' for nil

The nearby document-level parsing path already guards this kind of line number adjustment:

if parse_context.line_number
  ...
end

So the issue appears to be an asymmetry between the document-level path and the nested liquid tag path.

Trigger condition

This appears specific to a nested liquid line inside a {% liquid %} tag.

These controls do not trigger the same crash:

Liquid::Template.parse("{% liquid echo 1 %}")
Liquid::Template.parse("{% liquid %}")
Liquid::Template.parse("{% liquid render %}")

The render case fails cleanly as a Liquid parse error rather than escaping as a raw NoMethodError.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions