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_INSENSITIVE filter

What it means

Same guard as TEXT_MATCH but for FilterOperator.TEXT_MATCH_INSENSITIVE: the case-insensitive substring check calls `.lower()` on both sides, so both the filter value and the node's metadata value must be str. A TypeError is raised when either side is a non-string type, instead of an AttributeError from calling .lower() on an int. This is evaluated per candidate node during client-side filtering.

Source

Thrown at llama-index-core/llama_index/core/vector_stores/utils.py:148

            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)

        filter_matches_list = []
        for filter_ in filter_list:
            if isinstance(filter_, MetadataFilters):
                raise ValueError("Nested MetadataFilters are not supported.")

            filter_matches = True

View on GitHub (pinned to afd0fef371)

Solutions

  1. Pass a str value: `MetadataFilter(key="name", value="alice", operator=FilterOperator.TEXT_MATCH_INSENSITIVE)`.
  2. For collections use `FilterOperator.IN` / `ANY` / `CONTAINS` instead of text-match operators.
  3. Normalize metadata types at ingestion so filtered fields are always str (or always the intended type).
  4. Skip None values by using `FilterOperator.IS_EMPTY` for missing-field checks.

Example fix

# before
f = MetadataFilter(key="tags", value=["ai"], operator=FilterOperator.TEXT_MATCH_INSENSITIVE)

# after
f = MetadataFilter(key="tags", value="ai", operator=FilterOperator.TEXT_MATCH_INSENSITIVE)
# or for collections:
f = MetadataFilter(key="tags", value=["ai"], operator=FilterOperator.IN)
Defensive patterns

Strategy: type-guard

Validate before calling

def insensitive_filter_valid(value) -> bool:
    return isinstance(value, str)

Type guard

def is_insensitive_match_safe(filter_, sample_metadata: dict) -> bool:
    from llama_index.core.vector_stores import FilterOperator
    if filter_.operator is not FilterOperator.TEXT_MATCH_INSENSITIVE:
        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_INSENSITIVE" in str(e):
        # switch to IN for collections or coerce value to str, then rebuild query
        raise ValueError("use str values or FilterOperator.IN for lists") from e
    raise

Prevention

When it happens

Trigger: Querying with `operator=FilterOperator.TEXT_MATCH_INSENSITIVE` where the filter value is non-str (int, None, list) or where stored metadata under the filter key is numeric/None in any node being evaluated; e.g. `MetadataFilter(key="tags", value=["ai"], operator=TEXT_MATCH_INSENSITIVE)`.

Common situations: Passing arrays to a single-value operator (should use IN/ANY/CONTAINS); optional metadata fields that are None on some documents; mixed-type metadata after schema drift or multi-source ingestion; forgetting to stringify config-supplied filter values.

Related errors


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