{"record":{"id":"7572b341e274ed02","repo":"MemPalace/mempalace","slug":"unknown-backend-name-r-available-sorted-regi","errorCode":null,"errorMessage":"unknown backend {name!r}; available: {sorted(_registry.keys())}","messagePattern":"unknown backend (.+?); available: (.+?)","errorType":"exception","errorClass":"KeyError","httpStatus":null,"severity":"error","filePath":"mempalace/backends/registry.py","lineNumber":122,"sourceCode":"        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\n        return inst\n\n\ndef detect_backends_for_path(path: str) -> list[str]:\n    \"\"\"Return all registered backend names whose artifacts are present at ``path``.\n\n    Detection is a migration/protection aid for local palaces. Backends are\n    checked in registry-name order so callers get deterministic diagnostics if\n    a broken directory contains artifacts from more than one backend.\n    \"\"\"\n    _discover_entry_points()\n    detected = []\n    for name in sorted(_registry):\n        cls = _registry[name]\n        try:\n            if cls.detect(path):","sourceCodeStart":104,"sourceCodeEnd":140,"githubUrl":"https://github.com/MemPalace/mempalace/blob/06cb6987f02610784fefbad4b2bd5d026d164ba6/mempalace/backends/registry.py#L104-L140","documentation":"Raised by get_backend() when the named backend class is not registered — the instance-caching variant of the same lookup failure as get_backend_class. The message enumerates currently registered backend names (sorted registry keys).","triggerScenarios":"get_backend(name) with a typo'd/unregistered name, an optional backend whose dependency is not installed, or a plugin whose entry point did not load.","commonSituations":"Config-driven backend selection (env var / settings file) with a stale or misspelled value; deploying without the optional dependency for the configured backend; test code requesting a backend only registered under an extra.","solutions":["Use a name from the message's available list (verify with available_backends())","Install the matching optional extra / plugin package","Validate backend names against available_backends() at config load time, not at first use"],"exampleFix":"# before\nbackend = get_backend(\"sqlite\")  # not registered\n# after\nfrom mempalace.backends.registry import available_backends\nassert \"sqlite_exact\" in available_backends()\nbackend = get_backend(\"sqlite_exact\")","handlingStrategy":"validation","validationCode":"from mempalace.backends.registry import available_backends\nAVAILABLE = set(available_backends())\nif config.backend not in AVAILABLE:\n    raise ConfigError(f\"backend {config.backend!r} not in {sorted(AVAILABLE)}\")\nbackend = get_backend(config.backend)","typeGuard":"def is_registered_backend(name: str) -> bool:\n    return isinstance(name, str) and name in available_backends()","tryCatchPattern":"try:\n    backend = get_backend(name)\nexcept KeyError:\n    name = pick_from(available_backends())  # prompt user or fail with clear message\n    backend = get_backend(name)","preventionTips":["Validate backend config early, fail fast at startup","Keep an install/test step asserting the configured backend is registered"],"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"}