langchain-ai/langchain · error · ChevronError

unclosed tag at line {_CURRENT_LINE}

Error message

unclosed tag at line {_CURRENT_LINE}

What it means

Raised by the vendored Mustache engine (`langchain_core.utils.mustache`, used by `MustachePlaceholderFormatter`) when a tag is opened with the left delimiter (`{{`) but the right delimiter (`}}`) is never found in the remainder of the template. The message reports the line where the unclosed tag starts. The template cannot be parsed at all, so no rendering happens.

Source

Thrown at libs/core/langchain_core/utils/mustache.py:149

        ChevronError: If the set delimiter tag is unclosed.
    """
    tag_types = {
        "!": "comment",
        "#": "section",
        "^": "inverted section",
        "/": "end",
        ">": "partial",
        "=": "set delimiter?",
        "{": "no escape?",
        "&": "no escape",
    }

    # Get the tag
    try:
        tag, template = template.split(r_del, 1)
    except ValueError as e:
        msg = f"unclosed tag at line {_CURRENT_LINE}"
        raise ChevronError(msg) from e

    # Check for empty tags
    if not tag.strip():
        msg = f"empty tag at line {_CURRENT_LINE}"
        raise ChevronError(msg)

    # Find the type meaning of the first character
    tag_type = tag_types.get(tag[0], "variable")

    # If the type is not a variable
    if tag_type != "variable":
        # Then that first character is not needed
        tag = tag[1:]

    # If we might be a set delimiter tag
    if tag_type == "set delimiter?":
        # Double check to make sure we are
        if tag.endswith("="):

View on GitHub (pinned to e32fa9a52e)

Solutions

  1. Go to the reported line and close the tag or remove the stray `{{`.
  2. If the double braces are literal content (JSON, LaTeX), change delimiters with a `{{=<% %>=}}` set-delimiter tag or escape/replace the braces before rendering.
  3. Run `MustachePlaceholderFormatter` validation on templates at startup (compile/tokenize once) so the error surfaces before production traffic.
  4. If templates come from users, lint them with the tokenizer before accepting.

Example fix

# before
template = "Q: {{question\nA:"  # missing closing braces
MustachePlaceholderFormatter().format(template, question="hi")  # ChevronError: unclosed tag

# after
template = "Q: {{question}}\nA:"
MustachePlaceholderFormatter().format(template, question="hi")
Defensive patterns

Strategy: validation

Validate before calling

from langchain_core.utils.mustache import tokenize
from langchain_core.utils.mustache import ChevronError

def validate_mustache(template: str) -> None:
    try:
        list(tokenize(template))
    except ChevronError as e:
        raise ValueError(f"bad template: {e}") from e

Try / catch

try:
    out = MustachePlaceholderFormatter().format(template, **vars)
except ChevronError as e:
    # fall back to str.format or raw template
    out = template

Prevention

When it happens

Trigger: Rendering a prompt template through `MustachePlaceholderFormatter.format` (or `tokenize`) where the template contains an unmatched `{{`, e.g. `"Summarize: {{text"` or a literal `{{` intended as text (e.g. JSON examples embedded in a prompt) without escaping.

Common situations: Hand-written prompt templates with a typo (missing `}}`); embedding raw JSON or LaTeX (`{{ ... }}`) in a Mustache template without escaping; user-supplied templates passed to an agent loop that uses Mustache formatting; partial templates concatenated at runtime that cut a tag in half.

Related errors


AI-assisted analysis of langchain-ai/langchain@e32fa9a52e (2026-08-14). Data as JSON: /api/errors/069bf0623ac36fa6. Report an issue: GitHub.