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
BaiduDB._create_filter raises ValueError when a filter VALUE is not str, int, float, or bool. Values are string-formatted into the query expression, so unsupported types (None, list, dict, datetime) cannot be rendered safely and are rejected instead of coerced. Note bool passes because it subclasses int, but NoneType does not.
Source
Thrown at mem0/vector_stores/baidu.py:425
Create filter expression for queries.
Args:
filters (dict): Filter conditions.
Returns:
str: Filter expression.
"""
conditions = []
for key, value in filters.items():
if not self._SAFE_FILTER_KEY.match(key):
raise ValueError(f"Invalid filter key: {key!r}")
if isinstance(value, str):
escaped = value.replace("\\", "\\\\").replace('"', '\\"')
conditions.append(f'metadata["{key}"] = "{escaped}"')
elif isinstance(value, (int, float, bool)):
conditions.append(f'metadata["{key}"] = {value}')
else:
raise ValueError(
f"Filter value for {key!r} must be str, int, float, or bool, "
f"got {type(value).__name__}"
)
return " AND ".join(conditions)
View on GitHub (pinned to 001c235229)
Solutions
- Flatten filters to scalar equality comparisons: use str/int/float/bool values only.
- Convert None to a sentinel string (e.g. 'null') or omit the key, and stringify datetimes: value.isoformat().
- For range/in-list semantics, pre-compute on the application side or store a derived boolean/field, since BaiduDB only supports equality.
Example fix
# before
db.search(query, vectors, filters={"since": {"$gt": "2024-01-01"}}) # ValueError: got dict
# after
db.search(query, vectors, filters={"since_gt_2024_01_01": True}) Defensive patterns
Strategy: type-guard
Validate before calling
def to_scalar_filters(filters: dict) -> dict:
out = {}
for k, v in (filters or {}).items():
if v is None:
continue
if isinstance(v, (str, int, float, bool)):
out[k] = v.isoformat() if hasattr(v, "isoformat") else v
else:
raise ValueError(f"filter {k!r} must be scalar, got {type(v).__name__}")
return out
db.search(query, vectors, filters=to_scalar_filters(filters)) Type guard
def is_scalar_filter_value(v) -> bool:
return isinstance(v, (str, int, float, bool)) Prevention
- Define filters as TypedDict fields with scalar types so mypy catches dict/list values.
- Convert datetimes to ISO strings and drop Nones before calling search.
- Remember this backend is equality-only: express ranges as precomputed fields.
When it happens
Trigger: Calling search with filters={'role': None}, filters={'tags': ['a','b']}, filters={'when': {'$gt': 5}}, or any dict/list/None value. The type name is included in the message (got dict, got NoneType, got list).
Common situations: Optional metadata fields that are None when unset; passing Mongo/Qdrant-style filter DSLs ({'$gt': ...}, nested dicts) to a provider that only supports equality; serializing datetimes as datetime objects instead of ISO strings.
Related errors
- Filter value for ${key} must be str, int, float, or bool, go
- Invalid filter key: ${key}
- Invalid filter key: {key!r}
- Filter value for {key!r} must be str, int, float, or bool, g
- Filter value for {key!r} must be str, int, float, or bool, g
AI-assisted analysis of mem0ai/mem0@001c235229 (2026-08-15).
Data as JSON: /api/errors/f3c7c890c5d6b388.
Report an issue: GitHub.