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

  1. Flatten or stringify complex values before adding: `"authors": ", ".join(authors)`, `str(datetime)`, `json.dumps(nested)`.
  2. Keep only filterable scalar fields in metadata and move the rest into node content or a separate store.
  3. Use a store/code path that supports structured metadata (not flat_metadata mode) if you truly need nested values.
  4. 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

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


AI-assisted analysis of run-llama/llama_index@afd0fef371 (2026-08-15). Data as JSON: /api/errors/19f50febb6ebc8e9. Report an issue: GitHub.