langchain-ai/langchain · error · ValueError

Invalid variable name {var!r} in f-string template. Variable

Error message

Invalid variable name {var!r} in f-string template. Variable names cannot contain attribute access (.) or indexing ([]).

What it means

Raised by `validate_f_string_template` when a template using `template_format='f-string'` contains a replacement field whose variable name includes attribute access or indexing, such as `{obj.attr}` or `{items[0]}`. LangChain formats templates with `str.format`-style replacement but only allows plain variable names, because attribute/index access would require passing real objects rather than the plain values LangChain prompt inputs carry. The offending name is included via `{var!r}`.

Source

Thrown at libs/core/langchain_core/prompts/string.py:240

def _parse_f_string_fields(template: str) -> list[tuple[str, str | None]]:
    fields: list[tuple[str, str | None]] = []
    for _, field_name, format_spec, _ in Formatter().parse(template):
        if field_name is not None:
            fields.append((field_name, format_spec))
    return fields


def validate_f_string_template(template: str) -> list[str]:
    """Validate an f-string template and return its input variables."""
    input_variables = set()
    for var, format_spec in _parse_f_string_fields(template):
        if "." in var or "[" in var or "]" in var:
            msg = (
                f"Invalid variable name {var!r} in f-string template. "
                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)

View on GitHub (pinned to e32fa9a52e)

Solutions

  1. Restructure the input so the value is passed directly: pre-compute `name = user.name` and use `{name}` in the template
  2. If real attribute traversal is required, switch the template format to `template_format="jinja2"` (after installing jinja2), which supports attribute access
  3. For indexing, pass the element itself: compute `first = items[0]` and reference `{first}`

Example fix

# before
prompt = PromptTemplate.from_template("Hello {user.name}, you have {items[0]} message")

# after
prompt = PromptTemplate.from_template("Hello {name}, you have {first_message}")
prompt.format(name=user.name, first_message=items[0])
Defensive patterns

Strategy: validation

Validate before calling

import re

def has_clean_fstring_vars(template: str) -> bool:
    return not any(("." in v or "[" in v or "]" in v)
                   for v in re.findall(r"\{([a-zA-Z_][a-zA-Z0-9_.\[\]]*)\}", template))

assert has_clean_fstring_vars(template)  # before PromptTemplate.from_template(template)

Try / catch

try:
    p = PromptTemplate.from_template(template)
except ValueError as e:
    if "attribute access" in str(e) or "indexing" in str(e):
        # flatten inputs instead: pass user.name as name
        raise ValueError(f"flatten dotted/indexed inputs before templating: {e}") from e
    raise

Prevention

When it happens

Trigger: `PromptTemplate.from_template("Hello {user.name}")` or any template containing `{a.b}` / `{list[0]}` while `template_format` is the default 'f-string'. Validation runs during `check_valid_template` at construction (when validating) or during `validate_f_string_template` calls like variable inference.

Common situations: Copying Python f-string code (`f"{user.name}"`) into a prompt template verbatim; templates authored for Jinja2 (`{{ obj.attr }}` converted to `{obj.attr}`) where attribute access is expected; prompt engineers assuming full str.format semantics.

Related errors


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