mem0ai/mem0 · error · ValueError

Filter value for {key!r} must be str, int, float, or bool, g

Error message

Filter value for {key!r} must be str, int, float, or bool, got {type(value).__name__}

What it means

Raised by AzureAISearch._build_filter_expression when a filters dict passed to search() contains a value whose type is not str, int, float, or bool. The builder interpolates values directly into an OData filter expression ('key eq value'), so it must be able to render the value as a literal; lists, dicts, None, and nested objects cannot be rendered and are rejected.

Source

Thrown at mem0/vector_stores/azure_ai_search.py:207

                raise Exception(f"Insert failed for document {doc.get('id')}: {doc}")
        return response

    def _sanitize_key(self, key: str) -> str:
        return re.sub(r"[^\w]", "", key)

    def _build_filter_expression(self, filters):
        filter_conditions = []
        for key, value in filters.items():
            safe_key = self._sanitize_key(key)
            if isinstance(value, str):
                safe_value = value.replace("'", "''")
                condition = f"{safe_key} eq '{safe_value}'"
            elif isinstance(value, bool):
                condition = f"{safe_key} eq {str(value).lower()}"
            elif isinstance(value, (int, float)):
                condition = f"{safe_key} eq {value}"
            else:
                raise ValueError(
                    f"Filter value for {key!r} must be str, int, float, or bool, "
                    f"got {type(value).__name__}"
                )
            filter_conditions.append(condition)
        filter_expression = " and ".join(filter_conditions)
        return filter_expression

    def search(self, query, vectors, top_k=5, filters=None):
        """
        Search for similar vectors.

        Args:
            query (str): Query.
            vectors (List[float]): Query vector.
            top_k (int, optional): Number of results to return. Defaults to 5.
            filters (Dict, optional): Filters to apply to the search. Defaults to None.

        Returns:

View on GitHub (pinned to 001c235229)

Solutions

  1. Flatten list filters to a single scalar or use multiple scalar filters per key (Azure OData 'any/all' is not supported by this builder)
  2. Drop None values from the filter dict before calling search
  3. Serialize or omit dict/datetime values — store them in metadata at add() time, filter on scalar projections
  4. Validate the filter dict shape before the call (see validationCode in defense)

Example fix

# before
memory.search("q", user_id="u1", filters={'roles': ['admin'], 'tenant': None})

# after
memory.search("q", user_id="u1", filters={'role': 'admin'})
Defensive patterns

Strategy: type-guard

Validate before calling

def sanitize_filters(filters: dict | None) -> dict:
    if not filters:
        return {}
    bad = {k: type(v).__name__ for k, v in filters.items() if not isinstance(v, (str, int, float, bool))}
    if bad:
        raise ValueError(f'non-scalar filter values: {bad}')
    return filters

Type guard

def filters_are_scalar(filters) -> bool:
    return isinstance(filters, dict) and all(
        isinstance(v, (str, int, float, bool)) and not isinstance(v, (list, dict, type(None)))
        for v in filters.values()
    )

Try / catch

try:
    memory.search(q, user_id=uid, filters=filters)
except ValueError as e:
    if 'must be str, int, float, or bool' in str(e):
        filters = sanitize_filters(filters)
        results = memory.search(q, user_id=uid, filters=filters)
    else:
        raise

Prevention

When it happens

Trigger: Calling memory.search(query, user_id='u1', filters={'roles': ['admin']}) — list value; passing filters={'meta': None}; passing a nested dict filter={'user': {'id': 1}}; passing datetime objects.

Common situations: Forwarding arbitrary user metadata as filters; assuming filters support the same shapes as metadata stored at add() time; None values from optional request fields flowing into filters.

Related errors


AI-assisted analysis of mem0ai/mem0@001c235229 (2026-08-15). Data as JSON: /api/errors/ef6d16d9d591ee96. Report an issue: GitHub.