{"record":{"id":"41336df5f21e4611","repo":"MemPalace/mempalace","slug":"qdrant-marker-is-missing-remote-target-metadata","errorCode":null,"errorMessage":"qdrant marker is missing remote target metadata","messagePattern":"qdrant marker is missing remote target metadata","errorType":"exception","errorClass":"BackendMismatchError","httpStatus":null,"severity":"error","filePath":"mempalace/backends/qdrant.py","lineNumber":1249,"sourceCode":"        if not os.path.isfile(marker_path):\n            return None\n        try:\n            with open(marker_path, encoding=\"utf-8\") as f:\n                marker = json.load(f)\n        except (OSError, json.JSONDecodeError) as exc:\n            raise BackendMismatchError(f\"qdrant marker is unreadable: {marker_path}\") from exc\n        return marker if isinstance(marker, dict) else {}\n\n    def _validate_marker_target(self, palace: PalaceRef, config: _QdrantConfig) -> None:\n        marker = self._read_marker(palace)\n        if marker is None:\n            return\n        if marker.get(\"backend\") != self.name:\n            raise BackendMismatchError(\"qdrant marker does not identify the qdrant backend\")\n        expected = self._marker_target(palace, config)\n        actual = marker.get(\"qdrant\")\n        if not isinstance(actual, dict):\n            raise BackendMismatchError(\"qdrant marker is missing remote target metadata\")\n        mismatched = [\n            key for key, expected_value in expected.items() if actual.get(key) != expected_value\n        ]\n        if mismatched:\n            details = \", \".join(mismatched)\n            raise BackendMismatchError(\n                \"qdrant marker remote target does not match current configuration \"\n                f\"({details}); keep MEMPALACE_QDRANT_URL and namespace consistent \"\n                \"or use a fresh palace directory\"\n            )\n\n    def _write_marker(self, palace: PalaceRef, config: _QdrantConfig) -> None:\n        if not palace.local_path:\n            return\n        os.makedirs(palace.local_path, exist_ok=True)\n        try:\n            os.chmod(palace.local_path, 0o700)\n        except (OSError, NotImplementedError):","sourceCodeStart":1231,"sourceCodeEnd":1267,"githubUrl":"https://github.com/MemPalace/mempalace/blob/06cb6987f02610784fefbad4b2bd5d026d164ba6/mempalace/backends/qdrant.py#L1231-L1267","documentation":"Raised when the marker identifies itself as a qdrant marker but its \"qdrant\" field is missing or not a JSON object. The qdrant field carries the remote target metadata (URL, namespace) used for drift detection; without it the backend cannot verify the palace is being pointed at the same Qdrant deployment, so it refuses to open.","triggerScenarios":"Marker JSON parses and backend == \"qdrant\", but marker.get(\"qdrant\") is None, a string, a list, etc. Causes: hand-edited marker, marker written by an older version that did not include target metadata, or partial/truncated write that still left valid JSON.","commonSituations":"Upgrading mempalace from a version whose marker schema lacked the qdrant target block; scripts that regenerate marker files without the full schema; manual attempts to fork a palace by copying and editing the marker.","solutions":["Delete the stale marker and re-pin the palace with get_collection(..., create=True) against the intended Qdrant server (verify the remote collection exists first)","Upgrade mempalace so markers are written with the current schema","Avoid hand-editing marker files; let the backend write them"],"exampleFix":"// before\n# marker: {\"backend\": \"qdrant\"}  (no \"qdrant\" target block)\ncol = backend.get_collection(palace, \"drawers\")  # raises\n// after\nrm palacedir/qdrant-marker.json\ncol = backend.get_collection(palace, \"drawers\", create=True)  # writes full marker","handlingStrategy":"validation","validationCode":"def marker_has_target(palace_path: str, marker_name: str) -> bool:\n    try:\n        with open(os.path.join(palace_path, marker_name), encoding=\"utf-8\") as f:\n            m = json.load(f)\n        return isinstance(m.get(\"qdrant\"), dict)\n    except (OSError, json.JSONDecodeError):\n        return False","typeGuard":null,"tryCatchPattern":"from mempalace.backends.base import BackendMismatchError\ntry:\n    backend.get_collection(palace, name)\nexcept BackendMismatchError as e:\n    if \"missing remote target metadata\" in str(e):\n        reinitialize_marker()  # delete marker, reopen with create=True","preventionTips":["Upgrade mempalace before reusing old palaces so markers get current schema","Never hand-write marker files"],"tags":["qdrant","marker","schema","upgrade"],"backgroundTag":null,"analyzedSha":"06cb6987f02610784fefbad4b2bd5d026d164ba6","analyzedAt":"2026-08-15T03:03:36.213Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}