RyanCodrai/turbovec · error · TypeError

Both metadata value and filter value must be strings for the

Error message

Both metadata value and filter value must be strings for the TEXT_MATCH_INSENSITIVE operator

What it means

TypeError raised in _single_filter_match when a TEXT_MATCH_INSENSITIVE filter encounters a non-string — either the node's metadata value or the filter's comparison value. Substring matching (case-insensitive) is only defined for strings, and the reference impl's AttributeError on non-strings is replaced with this explicit type guard; both operands must be str for the match to proceed.

Source

Thrown at turbovec-python/python/turbovec/llama_index.py:771

        if op == FilterOperator.CONTAINS:
            return target in value
        if op == FilterOperator.TEXT_MATCH:
            # Case-SENSITIVE substring. `FilterOperator` defines
            # TEXT_MATCH and TEXT_MATCH_INSENSITIVE as distinct operators,
            # so folding case here would collapse that distinction and
            # leave no way to ask for a case-sensitive match. The type
            # guard is ours: the reference raises AttributeError on a
            # non-string (issue #302).
            if isinstance(target, str) and isinstance(value, str):
                return target in value
            raise TypeError(
                "Both metadata value and filter value must be strings "
                "for the TEXT_MATCH operator"
            )
        if _TEXT_MATCH_INSENSITIVE is not None and op == _TEXT_MATCH_INSENSITIVE:
            if isinstance(target, str) and isinstance(value, str):
                return target.lower() in value.lower()
            raise TypeError(
                "Both metadata value and filter value must be strings "
                "for the TEXT_MATCH_INSENSITIVE operator"
            )
        if op == FilterOperator.ALL:
            # Reference (`utils.py:152-153`): every element of `target`
            # must be present in the metadata value (which is typically
            # a list — tag-set matching).
            return all(t in value for t in target)
        if op == FilterOperator.ANY:
            return any(t in value for t in target)
        raise NotImplementedError(
            f"filter operator {op!r} not supported by TurboQuantVectorStore"
        )

    def query(self, query: VectorStoreQuery, **_: Any) -> VectorStoreQueryResult:
        # MMR / SVM / LINEAR_REGRESSION / HYBRID etc. all need access to
        # full-precision vectors (for pairwise diversity, learned scoring,
        # or sparse-dense fusion). turbovec discards full precision after

View on GitHub (pinned to ccab9f325e)

Solutions

  1. Store the metadata field as a string and pass a string filter value
  2. Normalize the value with str() on both ingestion and query sides
  3. Use EQ/IN operators for non-string fields

Example fix

// before
MetadataFilter(key="year", value=2024, operator=FilterOperator.TEXT_MATCH_INSENSITIVE)
// after
MetadataFilter(key="year", value="2024", operator=FilterOperator.TEXT_MATCH_INSENSITIVE)
Defensive patterns

Strategy: type-guard

Validate before calling

if op == FilterOperator.TEXT_MATCH_INSENSITIVE and not (isinstance(meta_val, str) and isinstance(filt_val, str)):
    raise TypeError("TEXT_MATCH_INSENSITIVE requires string values")

Try / catch

try:
    store.query(q)
except TypeError as e:
    if "TEXT_MATCH_INSENSITIVE" in str(e):
        coerce_filter_values_to_str(q.filters)
        store.query(q)
    else:
        raise

Prevention

When it happens

Trigger: Querying with FilterOperator.TEXT_MATCH_INSENSITIVE where the metadata value or filter value is an int, float, bool, or list.

Common situations: Case-insensitive search over numeric or boolean metadata fields; untyped filter values from user input.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


AI-assisted analysis of RyanCodrai/turbovec@ccab9f325e (2026-09-06). Data as JSON: /api/errors/e9b81aed2542519d. Report an issue: GitHub.