{"record":{"id":"042fdcbf1a81e227","repo":"MemPalace/mempalace","slug":"unknown-backend-name-r-available-available-ba","errorCode":null,"errorMessage":"unknown backend {name!r}; available: {available_backends()}","messagePattern":"unknown backend (.+?); available: (.+?)","errorType":"exception","errorClass":"KeyError","httpStatus":null,"severity":"error","filePath":"mempalace/backends/registry.py","lineNumber":106,"sourceCode":"                )\n                continue\n            _registry.setdefault(ep.name, cls)\n        _discovered = True\n\n\ndef available_backends() -> list[str]:\n    \"\"\"Return sorted list of all registered backend names.\"\"\"\n    _discover_entry_points()\n    return sorted(_registry.keys())\n\n\ndef get_backend_class(name: str) -> Type[BaseBackend]:\n    \"\"\"Return the registered backend class for ``name``.\"\"\"\n    _discover_entry_points()\n    try:\n        return _registry[name]\n    except KeyError as e:\n        raise KeyError(f\"unknown backend {name!r}; available: {available_backends()}\") from e\n\n\ndef get_backend(name: str) -> BaseBackend:\n    \"\"\"Return a long-lived instance of the named backend.\n\n    Instances are cached per-name; repeated calls return the same object.\n    Call :func:`reset_backends` in tests that need isolation.\n    \"\"\"\n    _discover_entry_points()\n    with _lock:\n        inst = _instances.get(name)\n        if inst is not None:\n            return inst\n        cls = _registry.get(name)\n        if cls is None:\n            raise KeyError(f\"unknown backend {name!r}; available: {sorted(_registry.keys())}\")\n        inst = cls()\n        _instances[name] = inst","sourceCodeStart":88,"sourceCodeEnd":124,"githubUrl":"https://github.com/MemPalace/mempalace/blob/06cb6987f02610784fefbad4b2bd5d026d164ba6/mempalace/backends/registry.py#L88-L124","documentation":"Raised by get_backend_class() when the requested backend name is not in the registry after built-in and entry-point discovery. The message lists the sorted set of available backend names to make configuration mistakes immediately visible.","triggerScenarios":"get_backend_class(\"qdrannt\") (typo), get_backend_class(\"milvus\") when the optional dependency providing it is not installed, or requesting a backend whose entry-point plugin failed to register.","commonSituations":"Typo'd MEMPALACE_BACKEND value; expecting a backend that ships as an extra (pip install mempalace[milvus]) that was not installed; plugin package present but its entry point metadata broken; older mempalace version lacking a newer backend.","solutions":["Read the error message and use one of the listed available names","Install the optional extra that provides the backend (e.g. uv sync --extra qdrant / pip install 'mempalace[<backend>]')","Check spelling/case of the backend name in config","Upgrade mempalace if the backend was added in a newer version"],"exampleFix":"# before\ncls = get_backend_class(\"Qdrant\")  # KeyError: unknown backend 'Qdrant'\n# after\ncls = get_backend_class(\"qdrant\")  # use exact lowercase name from available_backends()","handlingStrategy":"validation","validationCode":"from mempalace.backends.registry import available_backends\n\ndef safe_backend_class(name: str):\n    if name not in available_backends():\n        raise ValueError(f\"backend {name!r} unavailable; installed: {available_backends()}\")\n    return get_backend_class(name)","typeGuard":"def is_known_backend(name: str, known: list[str]) -> bool:\n    return isinstance(name, str) and name in known","tryCatchPattern":"try:\n    cls = get_backend_class(name)\nexcept KeyError as e:\n    log_and_list_available()  # message already enumerates available names\n    raise","preventionTips":["Validate configured backend names at startup against available_backends()","Install extras for optional backends in the same commit that configures them","Pin mempalace version so available backends are deterministic"],"tags":["registry","backend","configuration","keyerror"],"backgroundTag":null,"analyzedSha":"06cb6987f02610784fefbad4b2bd5d026d164ba6","analyzedAt":"2026-08-15T03:03:36.213Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}