langchain-ai/langchain · error · ValueError
{save_path} must be json or yaml
Error message
{save_path} must be json or yaml What it means
Raised by BaseLLM.save_to_disk (via save) when the target file's suffix is neither .json nor .yaml/.yml. The LLM configuration is serialized by inspecting the path extension, so any other extension is unsupported.
Source
Thrown at libs/core/langchain_core/language_models/llms.py:1439
"""
# Convert file to Path object.
save_path = Path(file_path)
directory_path = save_path.parent
directory_path.mkdir(parents=True, exist_ok=True)
# Fetch dictionary to save
prompt_dict = self._dict_for_compat()
if save_path.suffix == ".json":
with save_path.open("w", encoding="utf-8") as f:
json.dump(prompt_dict, f, indent=4)
elif save_path.suffix.endswith((".yaml", ".yml")):
with save_path.open("w", encoding="utf-8") as f:
yaml.dump(prompt_dict, f, default_flow_style=False)
else:
msg = f"{save_path} must be json or yaml"
raise ValueError(msg)
class LLM(BaseLLM):
"""Simple interface for implementing a custom LLM.
You should subclass this class and implement the following:
- `_call` method: Run the LLM on the given prompt and input (used by `invoke`).
- `_identifying_params` property: Return a dictionary of the identifying parameters
This is critical for caching and tracing purposes. Identifying parameters
is a dict that identifies the LLM.
It should mostly include a `model_name`.
Optional: Override the following methods to provide more optimizations:
- `_acall`: Provide a native async version of the `_call` method.
If not provided, will delegate to the synchronous version using
`run_in_executor`. (Used by `ainvoke`).View on GitHub (pinned to e32fa9a52e)
Solutions
- Rename the target file to end in .json (recommended, avoids the optional PyYAML dependency): e.g. Path('model.json')
- Or use .yaml / .yml if YAML output is preferred
- Normalize the suffix before saving: save_path = save_path.with_suffix('.json')
Example fix
# before
llm.save_to_disk(Path('model_config.cfg'))
# after
llm.save_to_disk(Path('model_config.json')) Defensive patterns
Strategy: validation
Validate before calling
from pathlib import Path
p = Path(save_path)
if p.suffix not in {'.json', '.yaml', '.yml'}:
p = p.with_suffix('.json')
llm.save(p) Type guard
def is_supported_save_path(p: 'Path') -> bool:
return p.suffix in {'.json', '.yaml', '.yml'} Try / catch
try:
llm.save(save_path)
except ValueError as e:
if 'must be json or yaml' in str(e):
llm.save(save_path.with_suffix('.json'))
else:
raise Prevention
- Normalize the extension before saving: path.with_suffix('.json')
- Extensions are compared case-sensitively — use lowercase .json/.yaml/.yml
- Prefer .json to avoid requiring PyYAML at load time
When it happens
Trigger: llm.save_to_disk(Path('model.cfg')), llm.save_to_disk('llm.txt'), or a path with no suffix. Only '.json', '.yaml', and '.yml' are accepted (checked on save_path.suffix, so '.yml' works via the endswith check).
Common situations: Using a generic config filename like model.conf or llm.pkl; case-sensitivity surprises like '.JSON' (suffix comparison is case-sensitive); building paths dynamically without normalizing the extension.
Related errors
- Got unexpected message type: {type_}
- File is not open. Use FileCallbackHandler as a context manag
- Failed to hash metadata: {e}. Please use a dict that can be
- No global cache was configured. Use `set_llm_cache`.to set a
- Invalid input type {type(model_input)}. Must be a PromptValu
AI-assisted analysis of langchain-ai/langchain@e32fa9a52e (2026-08-14).
Data as JSON: /api/errors/24033ecad95ea039.
Report an issue: GitHub.