MemPalace/mempalace · error · UnsupportedCapabilityError

{type(self).name} does not advertise supports_namespace_isol

Error message

{type(self).name} does not advertise supports_namespace_isolation; leave PalaceRef.namespace as None (got {palace.namespace!r})

What it means

A ValueError from _read_sidecar_seq_ids: the supplied sidecar DB's max_seq_id table contains BLOB-typed seq_id values. Such sidecars predate chromadb's type normalisation and are not a trustworthy restoration source, so the helper refuses rather than restore garbage values that would corrupt seq_id state.

Source

Thrown at mempalace/backends/base.py:643

    #: ``"analyze"`` (refresh planner/query statistics), ``"compact"`` (reclaim
    #: space, rewrite storage), ``"reindex"`` (build/rebuild secondary indexes).
    #: A backend with no analogue for a kind MUST omit it rather than declare a
    #: no-op, so a benchmark harness can trust the set. Backends MAY add their
    #: own kinds. ``run_maintenance`` raises ``UnsupportedMaintenanceKindError``
    #: for anything not listed here.
    maintenance_kinds: ClassVar[frozenset[str]] = frozenset()

    def require_namespace_support(self, palace: PalaceRef) -> None:
        """Raise if ``palace.namespace`` is set but this backend does not isolate by it.

        Call at the start of ``get_collection`` (and any other entry that
        accepts a :class:`PalaceRef`) so non-advertising backends never
        silently drop a tenant namespace (RFC 001 §4.4).
        """
        if palace.namespace is None:
            return
        if "supports_namespace_isolation" not in self.capabilities:
            raise UnsupportedCapabilityError(
                f"{type(self).name} does not advertise supports_namespace_isolation; "
                f"leave PalaceRef.namespace as None (got {palace.namespace!r})"
            )

    @abstractmethod
    def get_collection(
        self,
        *,
        palace: PalaceRef,
        collection_name: str,
        create: bool = False,
        options: Optional[dict] = None,
    ) -> BaseCollection: ...

    def close_palace(self, palace: PalaceRef) -> None:
        """Evict cached handles for a single palace. Default: no-op."""
        return None

View on GitHub (pinned to 06cb6987f0)

Solutions

  1. Use a sidecar from a chromadb version that stores seq_id as INTEGER (post-normalisation).
  2. Migrate the old sidecar first: rewrite max_seq_id rows converting the BLOB to its integer value, then pass the migrated file.
  3. Alternatively repair seq_ids without a sidecar (segment-scoped repair / threshold detection) instead of a legacy sidecar.

Example fix

# Migrate BLOB seq_ids to INTEGER before using the sidecar
import sqlite3
conn = sqlite3.connect(sidecar)
rows = conn.execute('SELECT segment_id, seq_id FROM max_seq_id').fetchall()
conn.execute('DELETE FROM max_seq_id')
conn.executemany('INSERT INTO max_seq_id(segment_id, seq_id) VALUES(?, ?)',
                 [(sid, int.from_bytes(v, 'big') if isinstance(v, bytes) else int(v)) for sid, v in rows])
conn.commit()
Defensive patterns

Strategy: validation

Validate before calling

import sqlite3
kind = sqlite3.connect(sidecar).execute(
    "SELECT DISTINCT typeof(seq_id) FROM max_seq_id").fetchall()
if any(k != 'integer' for (k,) in kind):
    raise SystemExit('legacy BLOB sidecar; migrate seq_ids to INTEGER first')

Try / catch

try:
    _read_sidecar_seq_ids(sidecar)
except ValueError as e:
    if 'BLOB-typed' in str(e):
        sidecar = migrate_blob_sidecar(sidecar)  # rewrite as INTEGER
        _read_sidecar_seq_ids(sidecar)

Prevention

When it happens

Trigger: Calling repair_max_seq_id(from_sidecar=...) with a sidecar created by an old chromadb version that stored seq_id as BLOB; the typeof(seq_id) check returns 'blob' for at least one segment.

Common situations: Restoring from a backup taken under an old chromadb; mixing chromadb versions between the palace creation and the repair; copying a sidecar from a legacy replica.

Related errors


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