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
- Flatten list filters to a single scalar or use multiple scalar filters per key (Azure OData 'any/all' is not supported by this builder)
- Drop None values from the filter dict before calling search
- Serialize or omit dict/datetime values — store them in metadata at add() time, filter on scalar projections
- 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
- Allow only scalar filter values in your API layer; strip None and reject lists
- Store list-like metadata at add() time, filter on scalar projections
- Add a unit test over your filter dict shapes before they reach mem0
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
- Filter value for {key!r} must be str, int, float, or bool, g
- filters must contain at least one of: user_id, agent_id, run
- Invalid filter key: ${key}
- Filter value for ${key} must be str, int, float, or bool, go
- Filter value for ${JSON.stringify(key)} must be a string, nu
AI-assisted analysis of mem0ai/mem0@001c235229 (2026-08-15).
Data as JSON: /api/errors/ef6d16d9d591ee96.
Report an issue: GitHub.