{"record":{"id":"98f920c1aefab712","repo":"bytedance/deer-flow","slug":"openviking-failure-policy-write-must-be-log-and-d","errorCode":null,"errorMessage":"OpenViking failure_policy.write must be 'log_and_drop' or 'raise'","messagePattern":"OpenViking failure_policy\\.write must be 'log_and_drop' or 'raise'","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"backend/packages/harness/deerflow/agents/memory/backends/openviking/config.py","lineNumber":141,"sourceCode":"            raise ValueError(f\"OpenViking default_peer_id must not start with the reserved prefix {GENERATED_PEER_PREFIX!r}\")\n        if not isfinite(self.timeout_seconds) or self.timeout_seconds <= 0:\n            raise ValueError(\"OpenViking timeout_seconds must be a finite value > 0\")\n        if not 1 <= self.search_top_k <= 100:\n            raise ValueError(\"OpenViking retrieval.top_k must be between 1 and 100\")\n        if self.score_threshold is not None and (not isfinite(self.score_threshold) or not 0 <= self.score_threshold <= 1):\n            raise ValueError(\"OpenViking retrieval.score_threshold must be a finite value between 0 and 1\")\n        if not 256 <= self.max_injection_chars <= 100_000:\n            raise ValueError(\"OpenViking retrieval.max_injection_chars must be between 256 and 100000\")\n        if self.content_mode not in {\"auto\", \"abstract\", \"overview\", \"read\"}:\n            raise ValueError(\"OpenViking retrieval.content_mode must be auto, abstract, overview, or read\")\n        if not self.injection_query:\n            raise ValueError(\"OpenViking retrieval.injection_query must not be empty\")\n        if self.startup_policy not in {\"fail_fast\", \"warn\"}:\n            raise ValueError(\"OpenViking startup_policy must be 'fail_fast' or 'warn'\")\n        if self.read_failure_policy not in {\"fail_open\", \"raise\"}:\n            raise ValueError(\"OpenViking failure_policy.read must be 'fail_open' or 'raise'\")\n        if self.write_failure_policy not in {\"log_and_drop\", \"raise\"}:\n            raise ValueError(\"OpenViking failure_policy.write must be 'log_and_drop' or 'raise'\")\n        if not 16 <= self.max_seen_message_ids <= 10_000:\n            raise ValueError(\"OpenViking max_seen_message_ids must be between 16 and 10000\")\n\n\ndef is_safe_peer_id(value: str) -> bool:\n    \"\"\"Return whether *value* is valid for an OpenViking actor peer.\"\"\"\n\n    return _SAFE_PEER_RE.fullmatch(value) is not None\n\n\ndef _mapping(value: Any, name: str) -> dict[str, Any]:\n    if value is None:\n        return {}\n    if not isinstance(value, dict):\n        raise ValueError(f\"OpenViking {name} must be a mapping\")\n    return dict(value)\n\n","sourceCodeStart":123,"sourceCodeEnd":159,"githubUrl":"https://github.com/bytedance/deer-flow/blob/1dd6ba1acb03700589994b0366c5d1c7d05e2eff/backend/packages/harness/deerflow/agents/memory/backends/openviking/config.py#L123-L159","documentation":"OpenVikingConfig._validate() rejects memory.backend_config.failure_policy.write values outside {'log_and_drop','raise'}. write_failure_policy controls whether a failed memory capture is logged and the conversation turn continues (log_and_drop, the default) or raises MemoryManagerError (raise). The value is lowercased before validation.","triggerScenarios":"Setting memory.backend_config.failure_policy.write to anything other than 'log_and_drop' or 'raise' — e.g. 'drop', 'warn', 'fail_open'. Raised during OpenVikingConfig.from_backend_config -> _validate() at manager construction.","commonSituations":"Assuming the read-side value 'fail_open' also works for writes; abbreviating 'log_and_drop' to 'drop' or 'log'; using 'warn' because startup_policy accepts it.","solutions":["Set memory.backend_config.failure_policy.write: log_and_drop (default; write failures are logged and skipped) or raise (write failures raise MemoryManagerError)","Remove the failure_policy.write key to accept the log_and_drop default","Restart the Gateway after the config edit"],"exampleFix":"# before (config.yaml)\nmemory:\n  backend_config:\n    failure_policy:\n      write: warn   # invalid\n\n# after\nmemory:\n  backend_config:\n    failure_policy:\n      write: log_and_drop","handlingStrategy":"validation","validationCode":"allowed = {\"log_and_drop\", \"raise\"}\nval = str((raw_backend_config.get(\"failure_policy\") or {}).get(\"write\", \"log_and_drop\")).strip().lower()\nassert val in allowed, f\"failure_policy.write must be one of {sorted(allowed)}, got {val!r}\"","typeGuard":"def is_valid_write_policy(value: object) -> bool:\n    return isinstance(value, str) and value.strip().lower() in {\"log_and_drop\", \"raise\"}","tryCatchPattern":"try:\n    OpenVikingMemoryManager.from_config(backend_config)\nexcept ValueError as exc:\n    raise SystemExit(f\"Invalid OpenViking memory config: {exc}\") from exc","preventionTips":["Remember the write side uses log_and_drop, not fail_open","Run OpenVikingConfig.from_backend_config as a config smoke test in CI","Omit failure_policy.write to use the log_and_drop default"],"tags":["openviking","config","validation","failure-policy"],"backgroundTag":null,"analyzedSha":"1dd6ba1acb03700589994b0366c5d1c7d05e2eff","analyzedAt":"2026-08-14T21:20:34.804Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}