Shopify/liquid · error · Liquid::SyntaxError

errors.syntax.doc_invalid_nested

errors.syntax.doc_invalid_nested

Error message

parse_context.locale.t("errors.syntax.doc_invalid_nested")

What it means

Liquid does not allow a `{% doc %}` block to be nested inside another `{% doc %}` block. raise_nested_doc_error raises SyntaxError with the localized 'errors.syntax.doc_invalid_nested' when a doc tag is encountered while already inside a doc block.

Solutions

  1. Remove the inner {% doc %} block; keep only one nesting level
  2. Document each snippet separately instead of wrapping composed snippets
  3. Refactor includes/renders so documented fragments are not embedded inside other doc blocks
  4. Add a pre-commit lint that detects nested doc tags

Example fix

// before
{% doc %}
  Outer.
  {% doc %}Inner.{% enddoc %}
{% enddoc %}
// after
{% doc %}
  Outer only.
{% enddoc %}
Defensive patterns

Strategy: validation

Validate before calling

def nested_doc?(source)
  depth = 0
  source.scan(/{%-?\s*(doc|enddoc)\b/).each do |t|
    depth += (t.include?('enddoc') ? -1 : 1)
    return true if depth > 1
  end
  false
end

Try / catch

begin
  Liquid::Template.parse(source)
rescue Liquid::SyntaxError => e
  raise "Nested doc blocks are invalid: #{e.message}"
end

Prevention

When it happens

Trigger: Placing `{% doc %} ... {% doc %} ... {% enddoc %} ... {% enddoc %}` — an inner doc opening tag inside an outer doc block's content.

Common situations: Merging snippet files where each section wraps itself in a doc block; templating tools that auto-generate documentation wrappers around already-documented snippets; copy-paste of a documented block into another documented block.

Related errors


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

Appendix: source

Thrown at lib/liquid/tags/doc.rb:78

    def blank?
      @body.empty?
    end

    def nodelist
      [@body]
    end

    private

    def ensure_valid_markup(tag_name, markup, parse_context)
      unless NO_UNEXPECTED_ARGS.match?(markup)
        raise SyntaxError, parse_context.locale.t("errors.syntax.block_tag_unexpected_args", tag: tag_name)
      end
    end

    def raise_nested_doc_error
      raise SyntaxError, parse_context.locale.t("errors.syntax.doc_invalid_nested")
    end
  end
end

View on GitHub (pinned to 807d45a6b3)