MemPalace/mempalace · error · UnsupportedCapabilityError
facet_counts does not support local-only filters
Error message
facet_counts does not support local-only filters
What it means
facet_counts() on the pgvector backend translates the where filter into SQL. Some filter shapes (per _requires_local_filter) cannot be expressed in SQL pushdown and would need row-by-row local evaluation, which facet counting does not implement — so it raises UnsupportedCapabilityError. Validation happens before the unmaterialized-table short-circuit, so the error fires consistently even for empty collections.
Source
Thrown at mempalace/backends/pgvector.py:1234
if self._marker_exists():
raise CollectionNotInitializedError(self._collection_name)
return 0
return self._client.count_rows(self._table)
def facet_counts(
self,
field: str,
where: Optional[dict] = None,
limit: int = 1000,
) -> dict[str, int]:
self._ensure_open()
# Validate the filter before the existence short-circuit so an
# unsupported local-only filter raises even on an unmaterialized
# collection — matches the order used by get()/lexical_search() and
# qdrant.facet_counts (PR #1868 review).
_validate_where(where)
if _requires_local_filter(where):
raise UnsupportedCapabilityError("facet_counts does not support local-only filters")
if not self._table_exists():
if self._marker_exists():
raise CollectionNotInitializedError(self._collection_name)
return {}
return self._client.facet_counts(self._table, field=field, where=where, limit=limit)
def lexical_search(self, *, query: str, n_results: int = 10, where: Optional[dict] = None):
_validate_where(where)
pushdown = None if _requires_local_filter(where) else where
rows = self._scroll(where=pushdown, with_embedding=False)
rows = [row for row in rows if _matches_where(row["metadata"], where)]
scores = _bm25_scores(query, [row["document"] for row in rows])
hits = [
LexicalHit(
id=row["id"],
document=row["document"],
metadata=row["metadata"],
score=score,View on GitHub (pinned to 06cb6987f0)
Solutions
- Simplify the filter to operators pgvector can push down (equality, $and/$or of simple clauses).
- Compute facet counts client-side: scroll/get the filtered rows and count field values in Python.
- Catch UnsupportedCapabilityError and degrade to a client-side aggregation path.
Example fix
# before
counts = col.facet_counts(field="room", where={"tags": {"$in": ["a", "b"]}})
# after
rows = col.get(where={"tags": {"$in": ["a", "b"]}}, include=["metadatas"])
counts = Counter(r["room"] for r in rows["metadatas"]) Defensive patterns
Strategy: fallback
Validate before calling
# only pushdown-safe filters: equality + $and/$or
safe = all(not isinstance(v, dict) or set(v) <= {"$eq"} for v in where.values()) if where else True
counts = col.facet_counts(field=f, where=where) if safe else client_side_facets(col, f, where) Type guard
def is_pushdown_safe(where: dict) -> bool:
return not _requires_local_filter(where) # if importable; else whitelist operators Try / catch
try:
counts = col.facet_counts(field="room", where=filters)
except UnsupportedCapabilityError:
rows = col.get(where=filters, include=["metadatas"])
counts = Counter(r["room"] for r in rows["metadatas"]) Prevention
- Keep facet filters simple (equality, $and/$or).
- Catch UnsupportedCapabilityError in generic facet tooling and fall back to client-side counting.
- Reuse one validated filter builder for facets across backends.
When it happens
Trigger: Calling facet_counts(field="room", where={"tags": {"$in": ["a","b"]}}) or any filter containing operators/shapes flagged as local-only by _requires_local_filter.
Common situations: Reusing a complex filter that worked for query() (which falls back to _query_local_exact) on facet_counts(); generic facet widgets that let users build arbitrary ChromaDB-style filters.
Related errors
- pgvector does not support maintenance kind {kind!r}
- pgvector backend requires a local palace path to anchor mism
- operator {key!r} not supported by qdrant
- operator {op!r} not supported by qdrant
- where_document operator {key!r} not supported
AI-assisted analysis of MemPalace/mempalace@06cb6987f0 (2026-08-15).
Data as JSON: /api/errors/58313b76bea7a152.
Report an issue: GitHub.