{"record":{"id":"3221f248f2decc95","repo":"bytedance/deer-flow","slug":"honcho-memory-recall-failed-exc","errorCode":null,"errorMessage":"honcho memory recall failed: {exc}","messagePattern":"honcho memory recall failed: (.+?)","errorType":"exception","errorClass":"MemoryManagerError","httpStatus":null,"severity":"error","filePath":"backend/packages/harness/deerflow/agents/memory/backends/honcho/honcho_manager.py","lineNumber":150,"sourceCode":"        return f\"{self._config.workspace_prefix}{_stable_id(user_id)}\"\n\n    def _user_peer(self, user_id: str) -> str:\n        return self._config.user_peer_overrides.get(user_id) or _stable_id(user_id)\n\n    # ── recall policy gate (get_context / search / get_memory) ───────────\n    def _read_or_fallback(self, fallback: Any, fn: Any) -> Any:\n        \"\"\"Single ``failure_policy.read`` gate for every recall path, mirroring\n        mem0's helper of the same name: fail-open (default) logs and returns\n        ``fallback``; ``fail_closed`` wraps into ``MemoryManagerError``. The\n        broad ``except Exception`` is the containment boundary — no client\n        exception may escape into ``MemoryMiddleware.after_agent``.\"\"\"\n        try:\n            return fn()\n        except MemoryManagerError:\n            raise\n        except Exception as exc:\n            if self._config.read_fail_closed:\n                raise MemoryManagerError(f\"honcho memory recall failed: {exc}\") from exc\n            logger.warning(\"honcho memory: recall failed (fail-open): %s\", exc)\n            return fallback\n\n    # ── Tier 1: write ────────────────────────────────────────────────────\n    def add(\n        self,\n        thread_id: str,\n        messages: list[Any],\n        *,\n        agent_name: str | None = None,\n        user_id: str | None = None,\n        trace_id: str | None = None,\n    ) -> None:\n        workspace = self._workspace(user_id)\n        if workspace is None or not user_id:\n            logger.debug(\"honcho memory: no resolvable user for thread %s; skipping write\", thread_id)\n            return\n        user_peer = self._user_peer(user_id)","sourceCodeStart":132,"sourceCodeEnd":168,"githubUrl":"https://github.com/bytedance/deer-flow/blob/1dd6ba1acb03700589994b0366c5d1c7d05e2eff/backend/packages/harness/deerflow/agents/memory/backends/honcho/honcho_manager.py#L132-L168","documentation":"Wrapped as MemoryManagerError by HonchoManager._read_or_fallback, the single failure_policy.read gate for every recall path. When read_fail_closed is true (failure_policy.read: fail_closed) and any exception other than an already-raised MemoryManagerError escapes a recall call (HTTP failure, timeout, Honcho server error), it is rethrown as MemoryManagerError; with the default fail_open policy the same exception is only logged at warning level and the fallback value (empty memory) is returned. The broad except is the containment boundary so no client exception escapes into MemoryMiddleware.after_agent.","triggerScenarios":"memory.manager_class: honcho with backend_config.failure_policy.read: fail_closed, then any Honcho recall (get_context/search during MemoryMiddleware.after_agent or a memory_search tool call) hitting a connection error, timeout (timeout_seconds default 10s), 4xx/5xx from the Honcho server, or unexpected response shape.","commonSituations":"Honcho server down or unreachable at base_url; wrong base_url; TLS/firewall issues; honcho slowed beyond timeout_seconds under load; operator switched to fail_closed to make memory outages visible and now every Honcho blip fails the agent run.","solutions":["Verify the Honcho server is reachable: curl the base_url (e.g. GET /health or /v1/... ) from the Gateway host","Check base_url correctness and network/DNS; fix any http/https or port mismatch in backend_config","If recalls are hitting timeout_seconds under load, raise timeout_seconds/connect_timeout_seconds in backend_config","If memory recall should degrade gracefully instead of failing the run, remove failure_policy.read: fail_closed to return to the default fail_open (log + inject nothing)"],"exampleFix":"# before (config.yaml)\nmemory:\n  manager_class: honcho\n  backend_config:\n    base_url: http://honcho:8000   # wrong host -> every recall raises\n    failure_policy:\n      read: fail_closed\n\n# after\nmemory:\n  manager_class: honcho\n  backend_config:\n    base_url: http://localhost:8000\n    failure_policy:\n      read: fail_open   # recall failures log a warning and inject no memory","handlingStrategy":"try-catch","validationCode":"import httpx\n\ndef honcho_reachable(base_url: str, timeout: float = 3.0) -> bool:\n    try:\n        return httpx.get(f\"{base_url.rstrip('/')}/health\", timeout=timeout).is_success\n    except httpx.HTTPError:\n        return False","typeGuard":null,"tryCatchPattern":"from deerflow.agents.memory import MemoryManagerError\n\ntry:\n    context = manager.get_context(thread_id=..., user_id=...)\nexcept MemoryManagerError as e:\n    # raised only when failure_policy.read == fail_closed;\n    # decide: fail the run, or degrade to no-memory and continue\n    logger.error(\"honcho recall failed (fail_closed): %s\", e)\n    context = \"\"","preventionTips":["Default to read: fail_open in production unless recall integrity is mandatory; fail_closed converts every Honcho blip into a run failure","Monitor for the 'honcho memory: recall failed (fail-open)' warning log — it is the early signal before anyone opts into fail_closed","Keep Honcho health-checked (uptime probe on base_url) and size timeout_seconds to real server latency"],"tags":["honcho","memory","network","runtime","fail-closed"],"backgroundTag":null,"analyzedSha":"1dd6ba1acb03700589994b0366c5d1c7d05e2eff","analyzedAt":"2026-08-14T21:20:34.804Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}