langchain-ai/langchain · error · ChevronError
unclosed set delimiter tag\nat line {_CURRENT_LINE}
Error message
unclosed set delimiter tag\nat line {_CURRENT_LINE} What it means
Raised by the Mustache tokenizer in `langchain_core.utils.mustache` for a malformed set-delimiter tag. A tag starting with `=` (e.g. `{{= ... }}`) must end with `=` before the closing delimiter — `{{=<% %>=}}` — to switch delimiters. If the trailing `=` is missing, the tag is ambiguous and rejected. The message includes the line number.
Source
Thrown at libs/core/langchain_core/utils/mustache.py:175
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("="):
tag_type = "set delimiter"
# Remove the equal sign
tag = tag[:-1]
# Otherwise we should complain
else:
msg = f"unclosed set delimiter tag\nat line {_CURRENT_LINE}"
raise ChevronError(msg)
elif (
# If we might be a no html escape tag
tag_type == "no escape?"
# And we have a third curly brace
# (And are using curly braces as delimiters)
and l_del == "{{"
and r_del == "}}"
and template.startswith("}")
):
# Then we are a no html escape tag
template = template[1:]
tag_type = "no escape"
# Strip the whitespace off the key and return
return ((tag_type, tag.strip()), template)
View on GitHub (pinned to e32fa9a52e)
Solutions
- Fix the tag to the exact form `{{=<new> <new>=}}` (leading `=`, space-separated new delimiters, trailing `=`).
- If you did not intend to change delimiters, escape or remove the leading `=` inside the tag.
- Tokenize templates once at startup to catch delimiter errors early.
Example fix
# before
template = "{{=<% %>}}\nHi <%name%>" # missing trailing '='
# after
template = "{{=<% %>=}}\nHi <%name%>" Defensive patterns
Strategy: validation
Validate before calling
import re
def valid_set_delimiters(template: str) -> bool:
# every set-delimiter tag must look like {{= X Y =}}
for m in re.finditer(r"\{\{=[^}]*\}\}", template):
if not re.fullmatch(r"\{\{=\s*\S+\s+\S+\s*=\}\}", m.group(0)):
return False
return True Try / catch
try:
list(tokenize(template))
except ChevronError as e:
raise ValueError(f"invalid template: {e}") from e Prevention
- Copy the set-delimiter idiom verbatim: {{=<new> <new>=}}.
- Tokenize templates in CI/startup.
When it happens
Trigger: A template containing `{{=<% %>}}` (forgot the closing `=`), or any tag whose first character is `=` but which does not end with `=`. Encountered when rendering via `MustachePlaceholderFormatter`/`tokenize`.
Common situations: Manually changing delimiters to embed literal `{{ }}` content (JSON, LaTeX) and mistyping the syntax; copying the set-delimiter idiom from docs with a typo; templates authored for a different Mustache dialect.
Related errors
- unclosed tag at line {_CURRENT_LINE}
- empty tag at 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/d3a47a83709fa2e3.
Report an issue: GitHub.