MemPalace/mempalace · error · UnsupportedFilterError

$nin requires a non-empty list for {field!r}

Error message

$nin requires a non-empty list for {field!r}

What it means

Raised in _translate_field() when the $nin operand is not a list or is empty — the mirror of the $in check. An empty 'not in' set is degenerate in Milvus filter syntax, so translation fails with UnsupportedFilterError before any request is made. Only $nin and $in have the list requirement; $eq/$ne accept scalars.

Source

Thrown at mempalace/backends/milvus.py:125


def _translate_field(field: str, expected: Any) -> str:
    field = _field_name(field)
    if isinstance(expected, dict):
        parts = []
        for op, operand in expected.items():
            if op == "$eq":
                parts.append(f"{field} == {_quote_value(operand)}")
            elif op == "$ne":
                parts.append(f"{field} != {_quote_value(operand)}")
            elif op == "$in":
                if not isinstance(operand, list) or not operand:
                    raise UnsupportedFilterError(f"$in requires a non-empty list for {field!r}")
                items = ", ".join(_quote_value(item) for item in operand)
                parts.append(f"{field} in [{items}]")
            elif op == "$nin":
                if not isinstance(operand, list) or not operand:
                    raise UnsupportedFilterError(f"$nin requires a non-empty list for {field!r}")
                items = ", ".join(_quote_value(item) for item in operand)
                parts.append(f"{field} not in [{items}]")
            elif op == "$gt":
                parts.append(f"{field} > {_quote_value(operand)}")
            elif op == "$gte":
                parts.append(f"{field} >= {_quote_value(operand)}")
            elif op == "$lt":
                parts.append(f"{field} < {_quote_value(operand)}")
            elif op == "$lte":
                parts.append(f"{field} <= {_quote_value(operand)}")
            elif op == "$contains":
                parts.append(f"{field} like {_like_value(operand)}")
            else:
                raise UnsupportedFilterError(f"operator {op!r} not supported by milvus")
        return " and ".join(parts)
    return f"{field} == {_quote_value(expected)}"

View on GitHub (pinned to 06cb6987f0)

Solutions

  1. Drop the $nin clause entirely when the exclusion list is empty — 'not in []' is equivalent to no filter
  2. Wrap scalars into a list: {"$nin": [value]}
  3. Guard with a builder that strips empty $nin keys before calling query

Example fix

// before
where = {"wing": {"$nin": excluded}}  # excluded == []
collection.query(query_texts=[q], where=where)

// after
where = {"wing": {"$nin": excluded}} if excluded else None
collection.query(query_texts=[q], where=where)
Defensive patterns

Strategy: validation

Validate before calling

def drop_empty_nin(where):
    if not where:
        return None
    out = {}
    for k, v in where.items():
        if isinstance(v, dict):
            if "$nin" in v and (not isinstance(v["$nin"], list) or not v["$nin"]):
                v = {op: val for op, val in v.items() if op != "$nin"}
                if not v:
                    continue
        out[k] = v
    return out or None

Try / catch

from mempalace.backends.base import UnsupportedFilterError
try:
    collection.query(query_texts=[q], where=where, n_results=k)
except UnsupportedFilterError as e:
    if "$nin" in str(e):
        where2 = {k: {op: val for op, val in v.items() if op != "$nin"} if isinstance(v, dict) else v for k, v in where.items()}
        return collection.query(query_texts=[q], where=where2, n_results=k)
    raise

Prevention

When it happens

Trigger: where={"wing": {"$nin": []}}, where={"room": {"$nin": "2024-01-01"}} (scalar instead of list), or exclusion lists computed at runtime that end up empty.

Common situations: 'Exclude these wings/rooms' filters where the exclusion set is data-driven and occasionally empty; porting Mongo queries where $nin: [] is accepted as 'match all'.

Related errors


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