{"record":{"id":"80c53232e67539e0","repo":"bytedance/deer-flow","slug":"backend-config-retrieval-adapter-config-retrieval","errorCode":null,"errorMessage":"backend_config.retrieval_adapter={config.retrieval_adapter!r} failed to load: {exc}","messagePattern":"backend_config\\.retrieval_adapter=(.+?) failed to load: (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"critical","filePath":"backend/packages/harness/deerflow/agents/memory/backends/deermem/deermem/core/storage.py","lineNumber":1537,"sourceCode":"        capabilities = {\"file\", \"markdown-facts\", \"global-summary-json\", \"revision\", \"journal\", \"fact-repository\", \"substring-fallback\"}\n        if self._retrieval is not None:\n            capabilities.add(\"retrieval\")\n        return capabilities\n\n\ndef create_storage(config: DeerMemConfig, retrieval: RetrievalPort | None = None) -> MemoryStorage:\n    if retrieval is None and config.retrieval_adapter:\n        try:\n            if config.retrieval_adapter == \"fts5\":\n                from .retrieval import create_fts5_retrieval\n\n                factory = create_fts5_retrieval\n            else:\n                module_path, factory_name = config.retrieval_adapter.rsplit(\".\", 1)\n                factory = getattr(importlib.import_module(module_path), factory_name)\n            retrieval = factory(config)\n        except Exception as exc:\n            raise ValueError(f\"backend_config.retrieval_adapter={config.retrieval_adapter!r} failed to load: {exc}\") from exc\n    storage_class_path = config.storage_class\n    if not storage_class_path or storage_class_path == \"file\":\n        return FileMemoryStorage(config, retrieval=retrieval)\n    try:\n        module_path, class_name = storage_class_path.rsplit(\".\", 1)\n        storage_class = getattr(importlib.import_module(module_path), class_name)\n        if not isinstance(storage_class, type) or not issubclass(storage_class, MemoryStorage):\n            raise TypeError(f\"Configured memory storage '{storage_class_path}' is not a MemoryStorage class\")\n        return storage_class(config)\n    except Exception as exc:\n        raise ValueError(f\"backend_config.storage_class={storage_class_path!r} failed to load: {exc}. Refusing to silently fall back because memory is persistent state.\") from exc\n","sourceCodeStart":1519,"sourceCodeEnd":1549,"githubUrl":"https://github.com/bytedance/deer-flow/blob/1dd6ba1acb03700589994b0366c5d1c7d05e2eff/backend/packages/harness/deerflow/agents/memory/backends/deermem/deermem/core/storage.py#L1519-L1549","documentation":"create_storage() resolves config.retrieval_adapter: the built-in 'fts5' string maps to a local factory, anything else is treated as 'module.path:factory_name' and imported dynamically. Any failure - bad path format (rsplit without dot), ImportError, missing attribute, or the factory itself raising - is wrapped in this ValueError with the original exception chained.","triggerScenarios":"config.yaml backend_config.retrieval_adapter: 'deermem.retrieval.custom:make_retrieval' where the module does not exist, the function name is misspelled, or the factory throws on the given config (e.g. missing sqlite/fts5 support).","commonSituations":"Renaming or moving a custom retrieval module without updating config; upgrading deermem so a third-party adapter's import path changed; an environment lacking the adapter's dependencies; a typo in the dotted path.","solutions":["Read the chained cause (__cause__) in the traceback - it names the real ImportError/AttributeError.","Fix the dotted path to 'module.sub:callable' exactly as importable in the installed environment; verify with python -c \"from x.y import z\".","For the built-in full-text search use the literal 'fts5'.","Ensure the factory's own dependencies are installed in the same venv/uv environment as the harness."],"exampleFix":"# before (config.yaml)\nbackend_config:\n  retrieval_adapter: \"deermem.retrieval.custom.make_retrieval\"  # wrong: not module:attr form? attr split ok but module missing\n\n# after\nbackend_config:\n  retrieval_adapter: \"myapp.memory:make_retrieval\"","handlingStrategy":"try-catch","validationCode":"def adapter_loads(adapter: str) -> bool:\n    if adapter == \"fts5\":\n        return True\n    try:\n        module_path, factory_name = adapter.rsplit(\".\", 1)\n        getattr(importlib.import_module(module_path), factory_name)\n        return True\n    except Exception:\n        return False\n\nassert adapter_loads(config.retrieval_adapter), \"retrieval_adapter path is not importable\"","typeGuard":null,"tryCatchPattern":"try:\n    storage = create_storage(config)\nexcept ValueError as exc:\n    if \"retrieval_adapter\" in str(exc):\n        logger.error(\"Memory retrieval adapter misconfigured: %s\", exc.__cause__)\n    raise","preventionTips":["Smoke-test dynamic adapter paths in CI with the production config.","Pin plugin package versions so import paths do not drift on upgrade.","Verify the adapter module is installed in the exact service environment (uv/venv), not just locally."],"tags":["memory","configuration","dynamic-import","deermem"],"backgroundTag":null,"analyzedSha":"1dd6ba1acb03700589994b0366c5d1c7d05e2eff","analyzedAt":"2026-08-14T21:20:34.804Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}