langchain-ai/langchain · error · ValueError

Unsupported template file format: '{resolved_path.suffix}'.

Error message

Unsupported template file format: '{resolved_path.suffix}'. Only '.txt' files are supported.

What it means

When a prompt config points at a template file via `template_path` (or `prefix_path`/`suffix_path`), `_load_template` reads the file only if its resolved suffix is `.txt`; any other extension raises this `ValueError`. The path is resolved (symlinks included) before the check, so a symlink named `x.txt` pointing to a non-`.txt` target is also caught.

Source

Thrown at libs/core/langchain_core/prompts/loading.py:111

        if var_name in config:
            msg = f"Both `{var_name}_path` and `{var_name}` cannot be provided."
            raise ValueError(msg)
        # Pop the template path from the config.
        template_path = Path(config.pop(f"{var_name}_path"))
        if not allow_dangerous_paths:
            _validate_path(template_path)
        # Resolve symlinks before checking the suffix so that a symlink named
        # "exploit.txt" pointing to a non-.txt file is caught.
        resolved_path = template_path.resolve()
        # Load the template.
        if resolved_path.suffix == ".txt":
            template = resolved_path.read_text(encoding="utf-8")
        else:
            msg = (
                f"Unsupported template file format: '{resolved_path.suffix}'. "
                "Only '.txt' files are supported."
            )
            raise ValueError(msg)
        # Set the template variable to the extracted variable.
        config[var_name] = template
    return config


def _load_examples(
    config: dict[str, Any], *, allow_dangerous_paths: bool = False
) -> dict[str, Any]:
    """Load examples if necessary."""
    if isinstance(config["examples"], list):
        pass
    elif isinstance(config["examples"], str):
        path = Path(config["examples"])
        if not allow_dangerous_paths:
            _validate_path(path)
        with path.open(encoding="utf-8") as f:
            if path.suffix == ".json":
                examples = json.load(f)

View on GitHub (pinned to e32fa9a52e)

Solutions

  1. Rename the template file to end in `.txt` (contents can still be any template syntax).
  2. Inline the template into the config under `template` instead of using `template_path`.
  3. Fix symlinks so both the link name and the resolved target end in `.txt`.

Example fix

# before
# {"_type": "prompt", "template_path": "prompts/greet.j2"}
load_prompt('prompt.json')  # ValueError

# after
# rename file to prompts/greet.txt
# {"_type": "prompt", "template_path": "prompts/greet.txt"}
load_prompt('prompt.json')
Defensive patterns

Strategy: validation

Validate before calling

from pathlib import Path
for key in ('template_path', 'prefix_path', 'suffix_path'):
    if key in config:
        p = Path(config[key]).resolve()
        if p.suffix != '.txt':
            raise ValueError(f'{key} must reference a .txt file, got {p.suffix}')
load_prompt_from_config(config)

Type guard

def is_txt_path(path: str | Path) -> bool:
    return Path(path).resolve().suffix == '.txt'

Prevention

When it happens

Trigger: Config with `"template_path": "templates/tmpl.j2"` (or `.md`, `.jinja`, no extension, etc.). Also when `template_path` is a `.txt` symlink whose resolved target has a different suffix.

Common situations: Teams storing prompts as `.j2`/`.jinja`/`.md` files; editors auto-appending extensions; symlinks from a `.txt` name into a templates directory with different naming.

Related errors


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