{"record":{"id":"ff2203b9f7ad41db","repo":"run-llama/llama_index","slug":"both-metadata-value-and-value-should-be-strings-to","errorCode":null,"errorMessage":"Both metadata_value and value should be strings to be used with a TEXT_MATCH filter","messagePattern":"Both metadata_value and value should be strings to be used with a TEXT_MATCH filter","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"llama-index-core/llama_index/core/vector_stores/utils.py","lineNumber":141,"sourceCode":"                return metadata_value != value\n            if operator == FilterOperator.GT:\n                return metadata_value > value\n            if operator == FilterOperator.GTE:\n                return metadata_value >= value\n            if operator == FilterOperator.LT:\n                return metadata_value < value\n            if operator == FilterOperator.LTE:\n                return metadata_value <= value\n            if operator == FilterOperator.IN:\n                return metadata_value in value\n            if operator == FilterOperator.NIN:\n                return metadata_value not in value\n            if operator == FilterOperator.CONTAINS:\n                return value in metadata_value\n            if operator == FilterOperator.TEXT_MATCH:\n                if isinstance(value, str) and isinstance(metadata_value, str):\n                    return value in metadata_value\n                raise TypeError(\n                    \"Both metadata_value and value should be strings to be used with a \"\n                    \"TEXT_MATCH filter\"\n                )\n            if operator == FilterOperator.TEXT_MATCH_INSENSITIVE:\n                if isinstance(value, str) and isinstance(metadata_value, str):\n                    return value.lower() in metadata_value.lower()\n                raise TypeError(\n                    \"Both metadata_value and value should be strings to be used with a \"\n                    \"TEXT_MATCH_INSENSITIVE filter\"\n                )\n            if operator == FilterOperator.ALL:\n                return all(val in metadata_value for val in value)\n            if operator == FilterOperator.ANY:\n                return any(val in metadata_value for val in value)\n\n            raise ValueError(f\"Invalid operator: {operator}\")\n\n        metadata = metadata_lookup_fn(node_id)","sourceCodeStart":123,"sourceCodeEnd":159,"githubUrl":"https://github.com/run-llama/llama_index/blob/afd0fef371831f9bda13e5af7167cf4e981278ab/llama-index-core/llama_index/core/vector_stores/utils.py#L123-L159","documentation":"Inside `build_metadata_filter_fn`'s operator dispatch, FilterOperator.TEXT_MATCH performs substring containment, which is only defined for strings. If either the filter's `value` or the stored `metadata_value` is not a str (int, list, None...), the code raises TypeError instead of attempting the comparison. This is a per-node-type guard: it fires during query-time filtering when types do not line up.","triggerScenarios":"Building a MetadataFilter with `operator=FilterOperator.TEXT_MATCH` and a non-string value (e.g. an int id), or querying where the metadata field keyed by `filter.key` holds a number/list/None in some nodes; used with SimpleVectorStore or any store that evaluates filters client-side via this function.","commonSituations":"Numeric fields (year, page) mistakenly filtered with TEXT_MATCH instead of EQ/GTE; metadata schemas that changed type over time (some docs store year as int, others as str); None values from optional fields; JSON ingestion that yields numbers where strings were expected.","solutions":["Use the right operator: `FilterOperator.EQ` for exact numeric matches, `TEXT_MATCH` only for string fields.","Coerce the filter value: `str(value)` when the field is genuinely textual.","Normalize the stored metadata to a consistent type at ingestion time (e.g. always store year as str).","Guard the query: check `isinstance(filter.value, str)` before issuing a TEXT_MATCH filter."],"exampleFix":"# before\nf = MetadataFilter(key=\"title\", value=42, operator=FilterOperator.TEXT_MATCH)\n\n# after\nf = MetadataFilter(key=\"title\", value=\"42\", operator=FilterOperator.TEXT_MATCH)\n# or exact numeric match:\nf = MetadataFilter(key=\"page\", value=42, operator=FilterOperator.EQ)","handlingStrategy":"type-guard","validationCode":"from llama_index.core.vector_stores import FilterOperator\n\ndef text_match_filter_valid(value) -> bool:\n    return isinstance(value, str)","typeGuard":"def is_text_match_safe(filter_, sample_metadata: dict) -> bool:\n    if filter_.operator is not FilterOperator.TEXT_MATCH:\n        return True\n    stored = sample_metadata.get(filter_.key)\n    return isinstance(filter_.value, str) and isinstance(stored, str)","tryCatchPattern":"try:\n    result = store.query(query)\nexcept TypeError as e:\n    if \"TEXT_MATCH\" in str(e):\n        raise ValueError(\"TEXT_MATCH requires str value and str metadata field\") from e\n    raise","preventionTips":["Reserve TEXT_MATCH for string fields; use EQ for numbers.","Enforce consistent metadata types at ingestion (e.g. year always str or always int).","Validate filter.value types against a metadata schema before querying."],"tags":["metadata-filters","type-error","text-match","python"],"backgroundTag":null,"analyzedSha":"afd0fef371831f9bda13e5af7167cf4e981278ab","analyzedAt":"2026-08-15T05:42:58.429Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}