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
Milvus._create_filter() only accepts filter values of str, int, float, bool, or the '*' wildcard; anything else (list, dict, None, tuple) cannot be rendered into the metadata["key"] == <literal> expression and raises ValueError.
Source
Thrown at mem0/vector_stores/milvus.py:171
filters (dict): filters [user_id, agent_id, run_id]
Returns:
str: formated filter.
"""
operands = []
for key, value in filters.items():
if not self._SAFE_FILTER_KEY.match(key):
raise ValueError(f"Invalid filter key: {key!r}")
if value == "*":
# Wildcard - match any value (MilvusDB doesn't have direct wildcard, so we skip this filter)
continue
elif isinstance(value, str):
escaped = value.replace("\\", "\\\\").replace('"', '\\"')
operands.append(f'(metadata["{key}"] == "{escaped}")')
elif isinstance(value, (int, float, bool)):
operands.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(operands)
def _parse_output(self, data: list):
"""
Parse the output data.
Args:
data (Dict): Output data.
Returns:
List[OutputData]: Parsed output data.
"""
memory = []
View on GitHub (pinned to 001c235229)
Solutions
- Flatten list values into multiple searches (one per value) and merge results, since only equality is supported
- Remove None/nested values from the filters dict before calling search
- Use '*' only as a bare string value meaning match-any (it is skipped)
Example fix
# before
filters = {'user_id': ['u1', 'u2']} # ValueError: must be str, int, float, or bool
results = m.search('q', filters=filters)
# after
results = []
for uid in ['u1', 'u2']:
results.extend(m.search('q', filters={'user_id': uid})) Defensive patterns
Strategy: validation
Validate before calling
def coerce_filters(filters):
out = {}
for k, v in (filters or {}).items():
if v is None or isinstance(v, (list, tuple, dict, set)):
continue # unsupported value type: skip or explode lists upstream
out[k] = v
return out Type guard
def is_supported_filter_value(v) -> bool:
return isinstance(v, (str, int, float, bool)) and not isinstance(v, (list, dict)) Try / catch
try:
m.search('query', filters=filters)
except ValueError as e:
if 'must be str, int, float, or bool' in str(e):
filters = coerce_filters(filters)
results = m.search('query', filters=filters)
else:
raise Prevention
- Remember mem0 Milvus filters are equality-only: no lists, None, or nested dicts
- Flatten list values into repeated searches if you need OR semantics
- Validate the filters dict shape in one shared helper before every search call
When it happens
Trigger: Passing filters={'user_id': ['u1','u2']} (IN-style list), {'run_id': None}, or a nested dict as a value — mem0's Milvus filter builder has no operator syntax, only equality.
Common situations: Porting filters from Qdrant/other stores that support list membership (match any); forgetting that mem0 search filters are equality-only; '*' wildcard misuse as a dict value.
Related errors
- Filter value for ${JSON.stringify(key)} must be a string, nu
- 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
AI-assisted analysis of mem0ai/mem0@001c235229 (2026-08-15).
Data as JSON: /api/errors/500c4b892a1194a2.
Report an issue: GitHub.