bytedance/deer-flow · error · NotImplementedError

search not supported by {type(self).__name__}

Error message

search not supported by {type(self).__name__}

What it means

The base MemoryManager.search() deliberately raises NotImplementedError naming the backend class: search is an optional capability, and only backends that override search() AND set supports_search=True advertise it. This default exists so unsupported retrieval fails loudly and immediately instead of silently returning empty results that would look like 'no memories found'.

Source

Thrown at backend/packages/harness/deerflow/agents/memory/manager.py:281

        """
        self.add(thread_id, messages, agent_name=agent_name, user_id=user_id)

    def search(
        self,
        query: str,
        top_k: int = 5,
        *,
        user_id: str | None = None,
        agent_name: str | None = None,
        category: str | None = None,
    ) -> list[dict[str, Any]]:
        """Search the bucket's memory for facts matching ``query``; return up to
        ``top_k`` ranked by relevance. ``category`` (optional) filters BEFORE the
        ``top_k`` slice so a category-scoped search is not starved by other
        categories' higher-ranked facts. Default: unsupported (raise); backends
        with retrieval override AND set ``supports_search = True`` (required for
        ``mode='tool'``)."""
        raise NotImplementedError(f"search not supported by {type(self).__name__}")

    def get_memory(
        self,
        *,
        user_id: str | None = None,
        agent_name: str | None = None,
    ) -> dict[str, Any]:
        """Return the full memory document for the bucket. Default: unsupported."""
        raise NotImplementedError(f"get_memory not supported by {type(self).__name__}")

    def delete_memory(
        self,
        *,
        user_id: str | None = None,
        agent_name: str | None = None,
    ) -> None:
        """Delete the entire memory document for the bucket. Default: unsupported
        (dead contract -- zero callers)."""

View on GitHub (pinned to 1dd6ba1acb)

Solutions

  1. Check the backend's supports_search ClassVar before calling search()
  2. Switch to a retrieval-capable backend ( DeerMem default file storage or honcho implement search) if you need programmatic search
  3. In custom backends, override search() and set supports_search=True

Example fix

# before
results = manager.search('user preferences')

# after
results = manager.search('user preferences') if type(manager).supports_search else []
Defensive patterns

Strategy: type-guard

Validate before calling

from deerflow.agents.memory.manager import MemoryManager
if type(manager).search is MemoryManager.search:
    return []  # backend has no retrieval capability; skip the call
return manager.search(query, top_k=5, user_id=user)

Type guard

def backend_can_search(manager) -> bool:
    from deerflow.agents.memory.manager import MemoryManager
    return type(manager).supports_search is True and type(manager).search is not MemoryManager.search

Try / catch

try:
    results = manager.search(query, user_id=user)
except NotImplementedError:
    results = []  # retrieval unsupported on this backend; degrade gracefully

Prevention

When it happens

Trigger: Calling manager.search(query, ...) on a backend that did not override search (e.g. the noop backend, or a custom backend in middleware mode). In supported configurations the mode='tool' instantiation validator (error 636) blocks this earlier; direct calls (e.g. custom code, /api/memory search endpoints) can still reach it.

Common situations: Custom integration code calling search() unconditionally across backends; tool-mode attempts on a passive-only backend that slipped past construction (e.g. constructed directly instead of via the validating path).

Related errors


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