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
- Go to the reported line and close the tag or remove the stray `{{`.
- If the double braces are literal content (JSON, LaTeX), change delimiters with a `{{=<% %>=}}` set-delimiter tag or escape/replace the braces before rendering.
- Run `MustachePlaceholderFormatter` validation on templates at startup (compile/tokenize once) so the error surfaces before production traffic.
- 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
- Tokenize templates once at startup/CI, not per request.
- Escape literal double braces (JSON, LaTeX) or switch delimiters with a set-delimiter tag.
- Keep templates in files under lint control rather than building them by string concatenation.
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
- empty tag at line {_CURRENT_LINE}
- unclosed set delimiter tag\nat line {_CURRENT_LINE}
- Trying to close tag "{tag_key}"\nLooks like it was not opene
- Unexpected EOF\nthe tag "{open_sections[-1]}" was never clos
- Jinja2 templates are not allowed during deserialization for
AI-assisted analysis of langchain-ai/langchain@e32fa9a52e (2026-08-14).
Data as JSON: /api/errors/069bf0623ac36fa6.
Report an issue: GitHub.