run-llama/llama_index · error · ValueError

Value for metadata must be one of (str, int, float, None)

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.

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.

Appendix: 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)