MemPalace/mempalace · error · UnsupportedFilterError

where_document operator {key!r} not supported

Error message

where_document operator {key!r} not supported

What it means

where_document filters on the qdrant backend support only $contains plus $and/$or composition over such clauses. _matches_where_document raises UnsupportedFilterError for any other operator (e.g. $regex, $eq on documents), refusing to guess rather than silently mis-filtering content.

Source

Thrown at mempalace/backends/qdrant.py:216

def _matches_where_document(document: str, where_document: Optional[dict]) -> bool:
    if not where_document:
        return True
    if not isinstance(where_document, dict):
        return False
    for key, value in where_document.items():
        if key == "$contains":
            if str(value) not in document:
                return False
            continue
        if key == "$and":
            if not all(_matches_where_document(document, clause) for clause in value or []):
                return False
            continue
        if key == "$or":
            if not any(_matches_where_document(document, clause) for clause in value or []):
                return False
            continue
        raise UnsupportedFilterError(f"where_document operator {key!r} not supported")
    return True


def _validate_write_batch(
    *,
    documents: list[str],
    ids: list[str],
    metadatas: Optional[list[dict]],
    embeddings: Optional[list[list[float]]],
) -> None:
    n = len(ids)
    if len(documents) != n:
        raise ValueError(f"documents length {len(documents)} does not match ids length {n}")
    if metadatas is not None and len(metadatas) != n:
        raise ValueError(f"metadatas length {len(metadatas)} does not match ids length {n}")
    if embeddings is not None and len(embeddings) != n:
        raise ValueError(f"embeddings length {len(embeddings)} does not match ids length {n}")

View on GitHub (pinned to 06cb6987f0)

Solutions

  1. Use {"$contains": "substring"} for content matching.
  2. Combine multiple $contains clauses with $and/$or when you need OR semantics.
  3. For regex needs, fetch broader results and apply re.search in your own code.

Example fix

# before
col.query(query_embeddings=[vec], where_document={"$regex": "note-"})

# after
col.query(query_embeddings=[vec], where_document={"$contains": "note-"})
Defensive patterns

Strategy: validation

Validate before calling

def validate_where_document(wd):
    def walk(node):
        for k, v in (node or {}).items():
            if k not in {"$contains", "$and", "$or"}:
                raise ValueError(f"where_document operator {k} unsupported; use $contains")
            if isinstance(v, (list, dict)):
                for child in (v if isinstance(v, list) else [v]):
                    if isinstance(child, dict): walk(child)
    walk(wd)
    return wd

Type guard

def is_supported_where_document(wd: dict) -> bool:
    return all(k in {"$contains", "$and", "$or"} for k in (wd or {}))

Try / catch

try:
    col.query(query_embeddings=vecs, where_document=wd)
except UnsupportedFilterError:
    # fall back to substring matching client-side
    wd = {"$contains": extract_substring(wd)}

Prevention

When it happens

Trigger: Calling query(where_document={"$regex": "note-.*"}) or get(where_document={"$eq": "exact text"}) on a qdrant collection.

Common situations: Porting ChromaDB filters that use $regex on documents; UI search features offering regex over content.

Related errors


AI-assisted analysis of MemPalace/mempalace@06cb6987f0 (2026-08-15). Data as JSON: /api/errors/fc50d37b8e321d36. Report an issue: GitHub.