run-llama/llama_index · error · TypeError
Both metadata_value and value should be strings to be used w
Error message
Both metadata_value and value should be strings to be used with a TEXT_MATCH filter
What it means
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.
Source
Thrown at llama-index-core/llama_index/core/vector_stores/utils.py:141
return metadata_value != value
if operator == FilterOperator.GT:
return metadata_value > value
if operator == FilterOperator.GTE:
return metadata_value >= value
if operator == FilterOperator.LT:
return metadata_value < value
if operator == FilterOperator.LTE:
return metadata_value <= value
if operator == FilterOperator.IN:
return metadata_value in value
if operator == FilterOperator.NIN:
return metadata_value not in value
if operator == FilterOperator.CONTAINS:
return value in metadata_value
if operator == FilterOperator.TEXT_MATCH:
if isinstance(value, str) and isinstance(metadata_value, str):
return value in metadata_value
raise TypeError(
"Both metadata_value and value should be strings to be used with a "
"TEXT_MATCH filter"
)
if operator == FilterOperator.TEXT_MATCH_INSENSITIVE:
if isinstance(value, str) and isinstance(metadata_value, str):
return value.lower() in metadata_value.lower()
raise TypeError(
"Both metadata_value and value should be strings to be used with a "
"TEXT_MATCH_INSENSITIVE filter"
)
if operator == FilterOperator.ALL:
return all(val in metadata_value for val in value)
if operator == FilterOperator.ANY:
return any(val in metadata_value for val in value)
raise ValueError(f"Invalid operator: {operator}")
metadata = metadata_lookup_fn(node_id)View on GitHub (pinned to afd0fef371)
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.
Example fix
# before f = MetadataFilter(key="title", value=42, operator=FilterOperator.TEXT_MATCH) # after f = MetadataFilter(key="title", value="42", operator=FilterOperator.TEXT_MATCH) # or exact numeric match: f = MetadataFilter(key="page", value=42, operator=FilterOperator.EQ)
Defensive patterns
Strategy: type-guard
Validate before calling
from llama_index.core.vector_stores import FilterOperator
def text_match_filter_valid(value) -> bool:
return isinstance(value, str) Type guard
def is_text_match_safe(filter_, sample_metadata: dict) -> bool:
if filter_.operator is not FilterOperator.TEXT_MATCH:
return True
stored = sample_metadata.get(filter_.key)
return isinstance(filter_.value, str) and isinstance(stored, str) Try / catch
try:
result = store.query(query)
except TypeError as e:
if "TEXT_MATCH" in str(e):
raise ValueError("TEXT_MATCH requires str value and str metadata field") from e
raise Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Both metadata_value and value should be strings to be used w
- Cannot filter stores that were persisted without metadata. P
- Vector Store only supports exact match filters. Please use E
- Value for metadata {key} must be one of (str, int, float, No
- Invalid operator: {operator}
AI-assisted analysis of run-llama/llama_index@afd0fef371 (2026-08-15).
Data as JSON: /api/errors/ff2203b9f7ad41db.
Report an issue: GitHub.