bytedance/deer-flow · critical · ValueError
backend_config.retrieval_adapter={config.retrieval_adapter!r
Error message
backend_config.retrieval_adapter={config.retrieval_adapter!r} failed to load: {exc} What it means
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.
Source
Thrown at backend/packages/harness/deerflow/agents/memory/backends/deermem/deermem/core/storage.py:1537
capabilities = {"file", "markdown-facts", "global-summary-json", "revision", "journal", "fact-repository", "substring-fallback"}
if self._retrieval is not None:
capabilities.add("retrieval")
return capabilities
def create_storage(config: DeerMemConfig, retrieval: RetrievalPort | None = None) -> MemoryStorage:
if retrieval is None and config.retrieval_adapter:
try:
if config.retrieval_adapter == "fts5":
from .retrieval import create_fts5_retrieval
factory = create_fts5_retrieval
else:
module_path, factory_name = config.retrieval_adapter.rsplit(".", 1)
factory = getattr(importlib.import_module(module_path), factory_name)
retrieval = factory(config)
except Exception as exc:
raise ValueError(f"backend_config.retrieval_adapter={config.retrieval_adapter!r} failed to load: {exc}") from exc
storage_class_path = config.storage_class
if not storage_class_path or storage_class_path == "file":
return FileMemoryStorage(config, retrieval=retrieval)
try:
module_path, class_name = storage_class_path.rsplit(".", 1)
storage_class = getattr(importlib.import_module(module_path), class_name)
if not isinstance(storage_class, type) or not issubclass(storage_class, MemoryStorage):
raise TypeError(f"Configured memory storage '{storage_class_path}' is not a MemoryStorage class")
return storage_class(config)
except Exception as exc:
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
View on GitHub (pinned to 1dd6ba1acb)
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.
Example fix
# before (config.yaml) backend_config: retrieval_adapter: "deermem.retrieval.custom.make_retrieval" # wrong: not module:attr form? attr split ok but module missing # after backend_config: retrieval_adapter: "myapp.memory:make_retrieval"
Defensive patterns
Strategy: try-catch
Validate before calling
def adapter_loads(adapter: str) -> bool:
if adapter == "fts5":
return True
try:
module_path, factory_name = adapter.rsplit(".", 1)
getattr(importlib.import_module(module_path), factory_name)
return True
except Exception:
return False
assert adapter_loads(config.retrieval_adapter), "retrieval_adapter path is not importable" Try / catch
try:
storage = create_storage(config)
except ValueError as exc:
if "retrieval_adapter" in str(exc):
logger.error("Memory retrieval adapter misconfigured: %s", exc.__cause__)
raise Prevention
- 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.
When it happens
Trigger: 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).
Common situations: 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.
Related errors
- backend_config.storage_class={storage_class_path!r} failed t
- DeerMem memory update requested but no LLM is configured (se
- Fact was not stored because memory.max_facts kept higher-con
- Missing or empty 'messages' key in {path}
- chat prompt template not found: {name} (searched: {searched}
AI-assisted analysis of bytedance/deer-flow@1dd6ba1acb (2026-08-14).
Data as JSON: /api/errors/80c53232e67539e0.
Report an issue: GitHub.