{"record":{"id":"af454a4128d99075","repo":"MemPalace/mempalace","slug":"type-self-name-does-not-advertise-supports-name","errorCode":null,"errorMessage":"{type(self).name} does not advertise supports_namespace_isolation; leave PalaceRef.namespace as None (got {palace.namespace!r})","messagePattern":"(.+?) does not advertise supports_namespace_isolation; leave PalaceRef\\.namespace as None \\(got (.+?)\\)","errorType":"exception","errorClass":"UnsupportedCapabilityError","httpStatus":null,"severity":"error","filePath":"mempalace/backends/base.py","lineNumber":643,"sourceCode":"    #: ``\"analyze\"`` (refresh planner/query statistics), ``\"compact\"`` (reclaim\n    #: space, rewrite storage), ``\"reindex\"`` (build/rebuild secondary indexes).\n    #: A backend with no analogue for a kind MUST omit it rather than declare a\n    #: no-op, so a benchmark harness can trust the set. Backends MAY add their\n    #: own kinds. ``run_maintenance`` raises ``UnsupportedMaintenanceKindError``\n    #: for anything not listed here.\n    maintenance_kinds: ClassVar[frozenset[str]] = frozenset()\n\n    def require_namespace_support(self, palace: PalaceRef) -> None:\n        \"\"\"Raise if ``palace.namespace`` is set but this backend does not isolate by it.\n\n        Call at the start of ``get_collection`` (and any other entry that\n        accepts a :class:`PalaceRef`) so non-advertising backends never\n        silently drop a tenant namespace (RFC 001 §4.4).\n        \"\"\"\n        if palace.namespace is None:\n            return\n        if \"supports_namespace_isolation\" not in self.capabilities:\n            raise UnsupportedCapabilityError(\n                f\"{type(self).name} does not advertise supports_namespace_isolation; \"\n                f\"leave PalaceRef.namespace as None (got {palace.namespace!r})\"\n            )\n\n    @abstractmethod\n    def get_collection(\n        self,\n        *,\n        palace: PalaceRef,\n        collection_name: str,\n        create: bool = False,\n        options: Optional[dict] = None,\n    ) -> BaseCollection: ...\n\n    def close_palace(self, palace: PalaceRef) -> None:\n        \"\"\"Evict cached handles for a single palace. Default: no-op.\"\"\"\n        return None\n","sourceCodeStart":625,"sourceCodeEnd":661,"githubUrl":"https://github.com/MemPalace/mempalace/blob/06cb6987f02610784fefbad4b2bd5d026d164ba6/mempalace/backends/base.py#L625-L661","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Use a sidecar from a chromadb version that stores seq_id as INTEGER (post-normalisation).","Migrate the old sidecar first: rewrite max_seq_id rows converting the BLOB to its integer value, then pass the migrated file.","Alternatively repair seq_ids without a sidecar (segment-scoped repair / threshold detection) instead of a legacy sidecar."],"exampleFix":"# Migrate BLOB seq_ids to INTEGER before using the sidecar\nimport sqlite3\nconn = sqlite3.connect(sidecar)\nrows = conn.execute('SELECT segment_id, seq_id FROM max_seq_id').fetchall()\nconn.execute('DELETE FROM max_seq_id')\nconn.executemany('INSERT INTO max_seq_id(segment_id, seq_id) VALUES(?, ?)',\n                 [(sid, int.from_bytes(v, 'big') if isinstance(v, bytes) else int(v)) for sid, v in rows])\nconn.commit()","handlingStrategy":"validation","validationCode":"import sqlite3\nkind = sqlite3.connect(sidecar).execute(\n    \"SELECT DISTINCT typeof(seq_id) FROM max_seq_id\").fetchall()\nif any(k != 'integer' for (k,) in kind):\n    raise SystemExit('legacy BLOB sidecar; migrate seq_ids to INTEGER first')","typeGuard":null,"tryCatchPattern":"try:\n    _read_sidecar_seq_ids(sidecar)\nexcept ValueError as e:\n    if 'BLOB-typed' in str(e):\n        sidecar = migrate_blob_sidecar(sidecar)  # rewrite as INTEGER\n        _read_sidecar_seq_ids(sidecar)","preventionTips":["Keep sidecar backups taken with the same chromadb version as the live palace.","After chromadb upgrades, check typeof(seq_id) before using old sidecars for restore."],"tags":["chromadb","sidecar","version-drift","sqlite","validation"],"backgroundTag":null,"analyzedSha":"06cb6987f02610784fefbad4b2bd5d026d164ba6","analyzedAt":"2026-08-15T03:03:36.213Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}