run-llama/llama_index · error · ValueError
Value for metadata {key} must be one of (str, int, float, No
Error message
Value for metadata {key} must be one of (str, int, float, None) What it means
Companion check to the key validation: `_validate_is_flat_dict` requires every metadata value to be a str, int, float, or None when flat metadata is enabled. Lists, dicts, booleans-subclassed types, datetimes, and nested objects are rejected because flat-metadata vector stores cannot filter on structured values. The message names the offending key, which usually points straight at the problematic field.
Source
Thrown at llama-index-core/llama_index/core/vector_stores/utils.py:35
)
DEFAULT_TEXT_KEY = "text"
DEFAULT_TEXT_RESOURCE_KEY = "text_resource"
DEFAULT_EMBEDDING_KEY = "embedding"
DEFAULT_DOC_ID_KEY = "doc_id"
def _validate_is_flat_dict(metadata_dict: dict) -> None:
"""
Validate that metadata dict is flat,
and key is str, and value is one of (str, int, float, None).
"""
for key, val in metadata_dict.items():
if not isinstance(key, str):
raise ValueError("Metadata key must be str!")
if not isinstance(val, (str, int, float, type(None))):
raise ValueError(
f"Value for metadata {key} must be one of (str, int, float, None)"
)
def node_to_metadata_dict(
node: BaseNode,
remove_text: bool = False,
text_field: str = DEFAULT_TEXT_KEY,
text_resource_field: str = DEFAULT_TEXT_RESOURCE_KEY,
flat_metadata: bool = False,
) -> Dict[str, Any]:
"""Common logic for saving Node data into metadata dict."""
# Using mode="json" here because BaseNode may have fields of type bytes (e.g. images in ImageBlock),
# which would cause serialization issues.
node_dict = node.model_dump(mode="json")
metadata: Dict[str, Any] = node_dict.get("metadata", {})
if flat_metadata:View on GitHub (pinned to afd0fef371)
Solutions
- Flatten or stringify complex values before adding: `"authors": ", ".join(authors)`, `str(datetime)`, `json.dumps(nested)`.
- Keep only filterable scalar fields in metadata and move the rest into node content or a separate store.
- Use a store/code path that supports structured metadata (not flat_metadata mode) if you truly need nested values.
- Add a pre-ingestion normalizer that raises your own descriptive error on unsupported types.
Example fix
# before
node = TextNode(text="...", metadata={"authors": ["A", "B"], "date": dt})
# after
node = TextNode(
text="...",
metadata={"authors": ", ".join(["A", "B"]), "date": dt.isoformat()},
) Defensive patterns
Strategy: validation
Validate before calling
ALLOWED = (str, int, float, type(None))
def validate_flat_metadata(metadata: dict) -> None:
for k, v in metadata.items():
if not isinstance(v, ALLOWED):
raise TypeError(f"metadata[{k!r}] has unsupported type {type(v).__name__}") Type guard
def is_flat_scalar_dict(d: dict) -> bool:
return all(
isinstance(k, str) and isinstance(v, (str, int, float, type(None)))
for k, v in d.items()
) Prevention
- Flatten lists/dicts at ingestion (join, json.dumps, or per-field columns).
- Convert datetimes/Decimals to str or float explicitly.
- Run a metadata lint step in CI over sample documents.
When it happens
Trigger: Adding nodes with `metadata={"authors": ["a", "b"]}`, `"date": datetime(...)`, `"attrs": {...}}` etc. through `node_to_metadata_dict(..., flat_metadata=True)`; ingesting rich dicts from APIs or ORMs without flattening.
Common situations: Ingesting JSON documents with nested objects or arrays directly as metadata; ORM model dumps containing datetime/Decimal; wanting list-valued filters on a store that only supports scalars; switching a store from one that tolerated complex metadata to one that validates.
Related errors
- Metadata key must be str!
- Metadata must be set
- Metadata must be set
- Tool name must be set
- spec_functions must be of type: List[Union[str, Tuple[str, s
AI-assisted analysis of run-llama/llama_index@afd0fef371 (2026-08-15).
Data as JSON: /api/errors/19f50febb6ebc8e9.
Report an issue: GitHub.