{"record":{"id":"6c7c30a8cdfaa9c9","repo":"MemPalace/mempalace","slug":"operator-k-r-not-supported-by-chroma-backend","errorCode":null,"errorMessage":"operator {k!r} not supported by chroma backend","messagePattern":"operator (.+?) not supported by chroma backend","errorType":"exception","errorClass":"UnsupportedFilterError","httpStatus":null,"severity":"error","filePath":"mempalace/backends/chroma.py","lineNumber":279,"sourceCode":"# (don't attempt recovery on segments with negligible data).\n_HNSW_MISSING_METADATA_DATA_FLOOR = 1024\n\n\ndef _validate_where(where: Optional[dict]) -> None:\n    \"\"\"Scan a where-clause for unknown operators and raise ``UnsupportedFilterError``.\n\n    Spec (RFC 001 §1.4): silent dropping of unknown operators is forbidden.\n    \"\"\"\n    if not where:\n        return\n    stack = [where]\n    while stack:\n        node = stack.pop()\n        if not isinstance(node, dict):\n            continue\n        for k, v in node.items():\n            if k.startswith(\"$\") and k not in _SUPPORTED_OPERATORS:\n                raise UnsupportedFilterError(f\"operator {k!r} not supported by chroma backend\")\n            if isinstance(v, dict):\n                stack.append(v)\n            elif isinstance(v, list):\n                stack.extend(x for x in v if isinstance(x, dict))\n\n\ndef _tokenize(text: str) -> list[str]:\n    if not text:\n        return []\n    return _TOKEN_RE.findall(text.lower())\n\n\ndef _bm25_scores(\n    query: str,\n    documents: list[str],\n    k1: float = 1.5,\n    b: float = 0.75,\n) -> list[float]:","sourceCodeStart":261,"sourceCodeEnd":297,"githubUrl":"https://github.com/MemPalace/mempalace/blob/06cb6987f02610784fefbad4b2bd5d026d164ba6/mempalace/backends/chroma.py#L261-L297","documentation":"A MaxSeqIdVerificationError raised at the end of repair_max_seq_id: after applying the repair plan, re-running poisoned-row detection still finds rows above the threshold. The repair wrote changes but verification failed, meaning the fix did not take effect for all planned segments; a backup of the pre-repair state is referenced in the message.","triggerScenarios":"The post-repair _detect_poisoned_max_seq_ids() call still returns rows — e.g. another process rewrote seq_ids between the UPDATE and the check, the plan missed segments, or the detection threshold/context differs between runs.","commonSituations":"Running the repair while chromadb (MCP server, miner) is live and rewriting the DB; concurrent repairs; a detection threshold passed differently on the retry.","solutions":["Stop all processes that touch the palace's chroma.sqlite3 (MCP server, mining hooks) and re-run the repair.","Compare the remaining segment ids in the message against result['segment_repaired'] to see which segments were missed.","If state looks wrong, restore from the backup path named in the message.","Re-run detection with the same threshold/segment arguments used for the repair to rule out argument drift."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"from mempalace import repair\npoisoned = repair._detect_poisoned_max_seq_ids(db_path, threshold=threshold)\nif poisoned:\n    ensure_no_live_chromadb_processes(palace_path)  # lsof/fuser check","typeGuard":null,"tryCatchPattern":"try:\n    repair_max_seq_id(palace_path, threshold=threshold)\nexcept MaxSeqIdVerificationError as e:\n    stop_palace_processes()\n    repair_max_seq_id(palace_path, threshold=threshold)  # retry with DB quiescent","preventionTips":["Run seq_id repairs only when no chromadb client (MCP server, miner, hooks) is live.","Use identical threshold/segment arguments across detection and repair passes.","Keep the automatic backup referenced in the error until verification passes."],"tags":["chromadb","seq-id","verification","concurrency","repair"],"backgroundTag":null,"analyzedSha":"06cb6987f02610784fefbad4b2bd5d026d164ba6","analyzedAt":"2026-08-15T03:03:36.213Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}