bytedance/deer-flow · error · ValueError
mem0 failure_policy must be a mapping {read, write}
Error message
mem0 failure_policy must be a mapping {read, write} What it means
Raised by Mem0Config.from_backend_config when memory.backend_config.failure_policy is present but is not a dict/mapping. The parser pops failure_policy and requires a mapping with at most the keys read and write (defaulting to fail_open / log_and_drop); a scalar, list, or null-adjacent value cannot express per-direction policy.
Source
Thrown at backend/packages/harness/deerflow/agents/memory/backends/mem0/config.py:76
failure_policy = cfg.pop("failure_policy", {}) or {}
unknown = (
set(cfg)
- {
"api_key_env",
"base_url",
"allow_insecure_http",
"top_k",
"score_threshold",
"max_injection_chars",
"timeout_seconds",
"startup_policy",
}
- _HOST_INJECTED_KEYS
)
if unknown:
raise ValueError(f"mem0 backend_config has unknown keys: {sorted(unknown)}")
if not isinstance(failure_policy, dict):
raise ValueError("mem0 failure_policy must be a mapping {read, write}")
unknown_fp = set(failure_policy) - {"read", "write"}
if unknown_fp:
raise ValueError(f"mem0 failure_policy has unknown keys: {sorted(unknown_fp)}")
allow_insecure_http = cfg.get("allow_insecure_http", False)
if not isinstance(allow_insecure_http, bool):
raise ValueError("mem0 allow_insecure_http must be a boolean")
config = cls(
api_key_env=str(cfg.get("api_key_env", "MEM0_API_KEY")),
base_url=str(cfg.get("base_url", "https://api.mem0.ai")).rstrip("/"),
allow_insecure_http=allow_insecure_http,
top_k=int(cfg.get("top_k", 8)),
score_threshold=float(cfg.get("score_threshold", 0.1)),
max_injection_chars=int(cfg.get("max_injection_chars", 12000)),
timeout_seconds=float(cfg.get("timeout_seconds", 10.0)),
startup_policy=str(cfg.get("startup_policy", "fail_fast")),
read_policy=str(failure_policy.get("read", "fail_open")),
write_policy=str(failure_policy.get("write", "log_and_drop")),View on GitHub (pinned to 1dd6ba1acb)
Solutions
- Write failure_policy as a mapping with read/write keys
- If you want the defaults (read: fail_open, write: log_and_drop), remove the failure_policy block entirely
- Re-check YAML indentation — the read:/write: lines must be nested under failure_policy
Example fix
# before (config.yaml)
memory:
backend_config:
failure_policy: fail_open # string, not a mapping
# after
memory:
backend_config:
failure_policy:
read: fail_open
write: log_and_drop Defensive patterns
Strategy: type-guard
Validate before calling
def failure_policy_shape_ok(backend_config: dict) -> bool:
fp = (backend_config or {}).get("failure_policy", {})
return fp is None or isinstance(fp, dict) Type guard
def is_failure_policy_mapping(v: object) -> bool:
"""failure_policy must be a mapping (or absent); str/list are rejected."""
return v is None or isinstance(v, dict) Prevention
- Use a YAML schema check (or example-based lint) that failure_policy is a nested mapping
- Remember the two-level shape: failure_policy.read / failure_policy.write, unlike flat keys such as startup_policy
When it happens
Trigger: Writing failure_policy: fail_open (a bare string) or failure_policy: [read, write] (a list) in config.yaml; also failure_policy: "" after templating.
Common situations: Assuming failure_policy takes a single word like other knobs (startup_policy does); YAML indentation that turns the mapping into a scalar; config templating/rendering that emits a non-map value.
Related errors
- mem0 backend_config has unknown keys: {sorted(unknown)}
- mem0 failure_policy has unknown keys: {sorted(unknown_fp)}
- Honcho backend: {key}[{k!r}] has an empty value; remove the
- mem0 allow_insecure_http must be a boolean
- mem0 startup_policy must be one of {sorted(_STARTUP_POLICIES
AI-assisted analysis of bytedance/deer-flow@1dd6ba1acb (2026-08-14).
Data as JSON: /api/errors/c596ae04f6990861.
Report an issue: GitHub.