MemPalace/mempalace · critical · UnsupportedCapabilityError

backend does not support facet_counts

Error message

backend does not support facet_counts

What it means

Raised as TruncationDetected when extraction returned exactly CHROMADB_DEFAULT_GET_LIMIT drawers and the on-disk SQLite count could not be cross-checked (sqlite_count is None, e.g. schema unreadable or DB locked). Because that exact count matches chromadb's internal default get() limit, the code cannot distinguish a genuine palace size from silent capping, so it refuses to overwrite the palace.

Source

Thrown at mempalace/backends/base.py:514

                kwargs["where"] = where
            batch = self.get(**kwargs)
            batch_meta = batch.metadatas if hasattr(batch, "metadatas") else batch.get("metadatas")
            if not batch_meta:
                break
            all_meta.extend(batch_meta)
            if len(batch_meta) < page_size:
                break
            offset += len(batch_meta)
        return all_meta

    def facet_counts(
        self,
        field: str,
        where: Optional[dict] = None,
        limit: int = 1000,
    ) -> dict[str, int]:
        """Return counts for each distinct value of a metadata field."""
        raise UnsupportedCapabilityError("backend does not support facet_counts")

    def maintenance_state(self) -> dict:
        """Return a structured snapshot of this collection's maintenance state.

        Free-form per backend (e.g. row count, whether a vector index exists,
        last-analyze age). Used by benchmark harnesses to record state
        alongside each latency/recall measurement so an un-analyzed store is
        not compared against a settled one (RFC 001). Defaults to empty.
        """
        return {}

    def run_maintenance(self, kind: str) -> "MaintenanceResult":
        """Run a maintenance ``kind`` and return an observable result (RFC 001).

        Backends advertise supported kinds in ``BaseBackend.maintenance_kinds``
        and override this. The default supports nothing, so every kind raises
        :class:`UnsupportedMaintenanceKindError`. Implementations MUST serialize
        concurrent same-kind runs and report ``already_running`` rather than

View on GitHub (pinned to 06cb6987f0)

Solutions

  1. Close any process holding chroma.sqlite3 (miners, MCP server) and retry so the SQLite cross-check can run.
  2. Independently verify the true count: query `SELECT COUNT(*) FROM embeddings` directly with the sqlite3 CLI.
  3. If the palace genuinely holds exactly that many drawers, re-run with --confirm-truncation-ok.
  4. If it holds more, use the direct-extract path to recover the capped rows instead of confirming.

Example fix

# Verify true count directly before confirming
# sqlite3 <palace>/chroma.sqlite3 'SELECT COUNT(*) FROM embeddings;'

# after verification
repair.rebuild_index(palace_path, confirm_truncation_ok=True)
Defensive patterns

Strategy: validation

Validate before calling

from mempalace import repair
count = repair.sqlite_drawer_count(palace_path)
if count is None:
    raise SystemExit('cannot cross-check; close processes holding chroma.sqlite3')

Try / catch

try:
    repair.check_extraction_safety(palace_path, extracted)
except repair.TruncationDetected as e:
    if e.sqlite_count is None:  # cap-signal variant
        true_count = direct_sqlite_count(palace_path)
        if true_count == extracted:
            rerun_with_confirm_truncation_ok()

Prevention

When it happens

Trigger: check_extraction_safety() sees cap_signal=True and sqlite_count=None. Happens when the palace holds exactly chromadb's default get limit rows, or extraction was capped, while sqlite_drawer_count() returned None due to version drift, missing tables, or a locked chroma.sqlite3.

Common situations: Large palaces hitting chromadb's default get() limit during repair; chromadb schema changes across upgrades making sqlite_drawer_count return None; running repair while another process holds the SQLite file.

Related errors


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