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

  1. Flatten filters to scalar equality comparisons: use str/int/float/bool values only.
  2. Convert None to a sentinel string (e.g. 'null') or omit the key, and stringify datetimes: value.isoformat().
  3. 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

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


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