{"record":{"id":"c596ae04f6990861","repo":"bytedance/deer-flow","slug":"mem0-failure-policy-must-be-a-mapping-read-write","errorCode":null,"errorMessage":"mem0 failure_policy must be a mapping {read, write}","messagePattern":"mem0 failure_policy must be a mapping (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"backend/packages/harness/deerflow/agents/memory/backends/mem0/config.py","lineNumber":76,"sourceCode":"        failure_policy = cfg.pop(\"failure_policy\", {}) or {}\n        unknown = (\n            set(cfg)\n            - {\n                \"api_key_env\",\n                \"base_url\",\n                \"allow_insecure_http\",\n                \"top_k\",\n                \"score_threshold\",\n                \"max_injection_chars\",\n                \"timeout_seconds\",\n                \"startup_policy\",\n            }\n            - _HOST_INJECTED_KEYS\n        )\n        if unknown:\n            raise ValueError(f\"mem0 backend_config has unknown keys: {sorted(unknown)}\")\n        if not isinstance(failure_policy, dict):\n            raise ValueError(\"mem0 failure_policy must be a mapping {read, write}\")\n        unknown_fp = set(failure_policy) - {\"read\", \"write\"}\n        if unknown_fp:\n            raise ValueError(f\"mem0 failure_policy has unknown keys: {sorted(unknown_fp)}\")\n        allow_insecure_http = cfg.get(\"allow_insecure_http\", False)\n        if not isinstance(allow_insecure_http, bool):\n            raise ValueError(\"mem0 allow_insecure_http must be a boolean\")\n\n        config = cls(\n            api_key_env=str(cfg.get(\"api_key_env\", \"MEM0_API_KEY\")),\n            base_url=str(cfg.get(\"base_url\", \"https://api.mem0.ai\")).rstrip(\"/\"),\n            allow_insecure_http=allow_insecure_http,\n            top_k=int(cfg.get(\"top_k\", 8)),\n            score_threshold=float(cfg.get(\"score_threshold\", 0.1)),\n            max_injection_chars=int(cfg.get(\"max_injection_chars\", 12000)),\n            timeout_seconds=float(cfg.get(\"timeout_seconds\", 10.0)),\n            startup_policy=str(cfg.get(\"startup_policy\", \"fail_fast\")),\n            read_policy=str(failure_policy.get(\"read\", \"fail_open\")),\n            write_policy=str(failure_policy.get(\"write\", \"log_and_drop\")),","sourceCodeStart":58,"sourceCodeEnd":94,"githubUrl":"https://github.com/bytedance/deer-flow/blob/1dd6ba1acb03700589994b0366c5d1c7d05e2eff/backend/packages/harness/deerflow/agents/memory/backends/mem0/config.py#L58-L94","documentation":"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.","triggerScenarios":"Writing failure_policy: fail_open (a bare string) or failure_policy: [read, write] (a list) in config.yaml; also failure_policy: \"\" after templating.","commonSituations":"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.","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"],"exampleFix":"# before (config.yaml)\nmemory:\n  backend_config:\n    failure_policy: fail_open   # string, not a mapping\n\n# after\nmemory:\n  backend_config:\n    failure_policy:\n      read: fail_open\n      write: log_and_drop","handlingStrategy":"type-guard","validationCode":"def failure_policy_shape_ok(backend_config: dict) -> bool:\n    fp = (backend_config or {}).get(\"failure_policy\", {})\n    return fp is None or isinstance(fp, dict)","typeGuard":"def is_failure_policy_mapping(v: object) -> bool:\n    \"\"\"failure_policy must be a mapping (or absent); str/list are rejected.\"\"\"\n    return v is None or isinstance(v, dict)","tryCatchPattern":null,"preventionTips":["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"],"tags":["config","mem0","memory","yaml","validation"],"backgroundTag":null,"analyzedSha":"1dd6ba1acb03700589994b0366c5d1c7d05e2eff","analyzedAt":"2026-08-14T21:20:34.804Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}