{"record":{"id":"d597e794bf5b6136","repo":"run-llama/llama_index","slug":"metadata-key-must-be-str","errorCode":null,"errorMessage":"Metadata key must be str!","messagePattern":"Metadata key must be str!","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"llama-index-core/llama_index/core/vector_stores/utils.py","lineNumber":33,"sourceCode":"    FilterOperator,\n    FilterCondition,\n)\n\n\nDEFAULT_TEXT_KEY = \"text\"\nDEFAULT_TEXT_RESOURCE_KEY = \"text_resource\"\nDEFAULT_EMBEDDING_KEY = \"embedding\"\nDEFAULT_DOC_ID_KEY = \"doc_id\"\n\n\ndef _validate_is_flat_dict(metadata_dict: dict) -> None:\n    \"\"\"\n    Validate that metadata dict is flat,\n    and key is str, and value is one of (str, int, float, None).\n    \"\"\"\n    for key, val in metadata_dict.items():\n        if not isinstance(key, str):\n            raise ValueError(\"Metadata key must be str!\")\n        if not isinstance(val, (str, int, float, type(None))):\n            raise ValueError(\n                f\"Value for metadata {key} must be one of (str, int, float, None)\"\n            )\n\n\ndef node_to_metadata_dict(\n    node: BaseNode,\n    remove_text: bool = False,\n    text_field: str = DEFAULT_TEXT_KEY,\n    text_resource_field: str = DEFAULT_TEXT_RESOURCE_KEY,\n    flat_metadata: bool = False,\n) -> Dict[str, Any]:\n    \"\"\"Common logic for saving Node data into metadata dict.\"\"\"\n    # Using mode=\"json\" here because BaseNode may have fields of type bytes (e.g. images in ImageBlock),\n    # which would cause serialization issues.\n    node_dict = node.model_dump(mode=\"json\")\n    metadata: Dict[str, Any] = node_dict.get(\"metadata\", {})","sourceCodeStart":15,"sourceCodeEnd":51,"githubUrl":"https://github.com/run-llama/llama_index/blob/afd0fef371831f9bda13e5af7167cf4e981278ab/llama-index-core/llama_index/core/vector_stores/utils.py#L15-L51","documentation":"`_validate_is_flat_dict` enforces that node metadata sent to a vector store is a flat dict with string keys. A non-str key can appear when integers or other hashables are used as dict keys (JSON round-trips sometimes introduce these), which most vector stores cannot index. The check runs inside `node_to_metadata_dict` with flat_metadata=True, so it fires at ingestion time, before anything is persisted.","triggerScenarios":"Adding nodes whose `metadata` dict contains non-string keys (e.g. `{1: \"chapter\"}`) to a store that validates flat metadata; building Document/TextNode objects from pandas rows or JSON where numeric dict keys survive.","commonSituations":"Loading metadata from JSON files parsed with integer-like keys; converting dataframe columns to dicts and using column positions as keys; programmatic metadata builders that accept arbitrary dicts; Pydantic models dumping enums or other non-str key types.","solutions":["Coerce all metadata keys to strings when building nodes: `{str(k): v for k, v in metadata.items()}`.","Fix the upstream data source so keys are emitted as strings (e.g. `json.load(..., object_keys_hook=...)` or dataframe `astype(str)` on key columns).","Add a validation step in your ingestion pipeline that rejects non-str keys early with a clearer message."],"exampleFix":"# before\nnode = TextNode(text=\"...\", metadata={101: \"intro\"})  # int key\n\n# after\nnode = TextNode(text=\"...\", metadata={str(k): v for k, v in raw_meta.items()})","handlingStrategy":"validation","validationCode":"def normalize_metadata_keys(metadata: dict) -> dict:\n    bad = [k for k in metadata if not isinstance(k, str)]\n    if bad:\n        raise TypeError(f\"non-str metadata keys: {bad!r}\")\n    return metadata","typeGuard":"def has_str_keys(metadata: dict) -> bool:\n    return all(isinstance(k, str) for k in metadata)","tryCatchPattern":"try:\n    store.add(nodes)\nexcept ValueError as e:\n    if \"key must be str\" in str(e):\n        nodes = [n.with metadata normalized]  # fix keys, then retry once\n    raise","preventionTips":["Coerce keys with str(k) at the edge of your ingestion pipeline.","Validate loaded JSON/dict metadata before constructing nodes.","Add a schema check (pydantic model with str-keyed fields) for metadata."],"tags":["metadata","validation","ingestion","python"],"backgroundTag":null,"analyzedSha":"afd0fef371831f9bda13e5af7167cf4e981278ab","analyzedAt":"2026-08-15T05:42:58.429Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}