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

  1. Read the chained cause (__cause__) in the traceback - it names the real ImportError/AttributeError.
  2. Fix the dotted path to 'module.sub:callable' exactly as importable in the installed environment; verify with python -c "from x.y import z".
  3. For the built-in full-text search use the literal 'fts5'.
  4. 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

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


AI-assisted analysis of bytedance/deer-flow@1dd6ba1acb (2026-08-14). Data as JSON: /api/errors/80c53232e67539e0. Report an issue: GitHub.