MemPalace/mempalace · error · UnsupportedFilterError
$and requires a non-empty list of clauses
Error message
$and requires a non-empty list of clauses
What it means
Raised in _translate_clause() when a top-level (or nested) $and key has a value that is not a non-empty list. $and composes sub-clauses, so its operand must be a list of at least one clause dict; anything else (dict, string, empty list) is an UnsupportedFilterError. Each sub-clause is itself recursively translated.
Source
Thrown at mempalace/backends/milvus.py:153
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)}"
def _translate_clause(clause: dict) -> str:
if not isinstance(clause, dict):
raise UnsupportedFilterError(f"where clause must be a dict, got {type(clause).__name__}")
if not clause:
return ""
parts = []
for key, value in clause.items():
if key == "$and":
if not isinstance(value, list) or not value:
raise UnsupportedFilterError("$and requires a non-empty list of clauses")
nested = [_translate_clause(item) for item in value]
parts.append("(" + " and ".join(part for part in nested if part) + ")")
elif key == "$or":
if not isinstance(value, list) or not value:
raise UnsupportedFilterError("$or requires a non-empty list of clauses")
nested = [_translate_clause(item) for item in value]
parts.append("(" + " or ".join(part for part in nested if part) + ")")
elif key.startswith("$"):
raise UnsupportedFilterError(f"operator {key!r} not supported by milvus")
else:
parts.append(_translate_field(key, value))
return " and ".join(part for part in parts if part)
def translate_where(where: Optional[dict]) -> str:
"""Translate the portable metadata where DSL into a Milvus filter string."""
if not where:
return ""View on GitHub (pinned to 06cb6987f0)
Solutions
- Use list form: {"$and": [{"a": 1}, {"b": 2}]}
- Remember sibling keys in one dict are already ANDed — {"a": 1, "b": 2} needs no $and
- When the operand list may be empty, skip $and and pass None/{} as the where clause
Example fix
// before
where = {"$and": {"wing": "alice", "room": "2024"}}
// after
where = {"$and": [{"wing": "alice"}, {"room": "2024"}]}
# or simply
where = {"wing": "alice", "room": "2024"} Defensive patterns
Strategy: validation
Validate before calling
def build_and(clauses):
clauses = [c for c in clauses if c]
if not clauses:
return None
if len(clauses) == 1:
return clauses[0]
return {"$and": clauses} # every element a dict, list never empty Try / catch
from mempalace.backends.base import UnsupportedFilterError
try:
collection.query(query_texts=[q], where=where, n_results=k)
except UnsupportedFilterError as e:
if "$and" in str(e):
raise ValueError("$and must be a non-empty list of clause dicts") from e
raise Prevention
- Prefer flat sibling keys over $and — they are ANDed implicitly
- Use a build_and() helper that never emits empty lists
- Remember $and takes a LIST, not a dict
When it happens
Trigger: where={"$and": {"a": 1, "b": 2}} (dict instead of list), {"$and": []}, or {"$and": ["a=1"]} where the element later fails the dict check (error 25).
Common situations: Assuming $and takes a dict of conditions (some DSLs allow both shapes); programmatically building conjunctions that collapse to zero when a filter list is empty.
Related errors
- operator {op!r} not supported by milvus
- $or requires a non-empty list of clauses
- Milvus filters do not support null comparisons
- Milvus filter field {name!r} is not a safe identifier
- $in requires a non-empty list for {field!r}
AI-assisted analysis of MemPalace/mempalace@06cb6987f0 (2026-08-15).
Data as JSON: /api/errors/7437be373ce49298.
Report an issue: GitHub.