langchain-ai/langchain · error · ValueError
Invalid format specifier in f-string template. Nested replac
Error message
Invalid format specifier in f-string template. Nested replacement fields are not allowed.
What it means
Raised by `validate_f_string_template` when a replacement field's format specifier itself contains braces, e.g. `{value:>{width}}`. Nested replacement fields are legal in raw Python f-strings but LangChain's template formatting does not support them, so validation rejects the template with `ValueError` before any render attempt.
Source
Thrown at libs/core/langchain_core/prompts/string.py:255
f"Variable names cannot contain attribute "
f"access (.) or indexing ([])."
)
raise ValueError(msg)
if var.isdigit():
msg = (
f"Invalid variable name {var!r} in f-string template. "
f"Variable names cannot be all digits as they are interpreted "
f"as positional arguments."
)
raise ValueError(msg)
if format_spec and ("{" in format_spec or "}" in format_spec):
msg = (
"Invalid format specifier in f-string template. "
"Nested replacement fields are not allowed."
)
raise ValueError(msg)
input_variables.add(var)
return sorted(input_variables)
def check_valid_template(
template: str, template_format: str, input_variables: list[str]
) -> None:
"""Check that template string is valid.
Args:
template: The template string.
template_format: The template format.
Should be one of `'f-string'` or `'jinja2'`.
input_variables: The input variables.
View on GitHub (pinned to e32fa9a52e)
Solutions
- Hard-code the width in the format spec: `{price:>10.2f}`
- Compute the padded string in Python before formatting the prompt: `padded = f"{price:>{width}.2f}"` then use `{padded}` in the template
- For loop-driven dynamic layout, render the whole fragment with `template_format="jinja2"` and Jinja2 filters (requires jinja2 installed)
Example fix
# before
prompt = PromptTemplate.from_template("total: {price:>{width}.2f}")
# after
padded_total = f"{price:>{width}.2f}"
prompt = PromptTemplate.from_template("total: {padded_total}")
prompt.format(padded_total=padded_total) Defensive patterns
Strategy: validation
Validate before calling
import re
def has_no_nested_format_spec(template: str) -> bool:
for spec in re.findall(r"\{[^{}]+:([^{}]*)\}", template):
if "{" in spec or "}" in spec:
return False
return True
assert has_no_nested_format_spec(template) Prevention
- Keep dynamic layout (widths, padding) in Python code, not in the template spec
- Hard-code widths in format specs: {price:>10.2f}
- Use jinja2 filters for dynamic alignment if truly needed
When it happens
Trigger: A template like `"{price:>{width}.2f}"` or `{num:{fill}<{width}}` used with the default f-string `template_format`. The check `format_spec and ("{" in format_spec or "}" in format_spec)` trips as soon as the field is parsed.
Common situations: Porting display/alignment code that uses dynamic widths into prompt templates; attempting table-style padding inside prompts; copy-pasting f-strings from Python formatting guides.
Related errors
- Invalid variable name {var!r} in f-string template. Variable
- Invalid variable name {var!r} in f-string template. Variable
- Invalid prompt schema; check for mismatched or missing input
- Saving an example selector is not currently supported
- Loading {config_type} prompt not supported
AI-assisted analysis of langchain-ai/langchain@e32fa9a52e (2026-08-14).
Data as JSON: /api/errors/6c10261590b2a923.
Report an issue: GitHub.