{"record":{"id":"4457e42f307b341c","repo":"bytedance/deer-flow","slug":"failed-to-create-memory-fact","errorCode":null,"errorMessage":"Failed to create memory fact.","messagePattern":"Failed to create memory fact\\.","errorType":"http","errorClass":"HTTPException","httpStatus":500,"severity":"error","filePath":"backend/app/gateway/routers/memory.py","lineNumber":330,"sourceCode":"async def create_memory_fact_endpoint(request: FactCreateRequest, http_request: Request) -> MemoryResponse:\n    \"\"\"Create a single fact manually.\"\"\"\n    manager = await asyncio.to_thread(get_memory_manager)\n    try:\n        memory_data, fact_id = await asyncio.to_thread(\n            manager.create_fact,\n            content=request.content,\n            category=request.category,\n            confidence=request.confidence,\n            user_id=_resolve_memory_user_id(http_request),\n        )\n    except NotImplementedError:\n        raise _unsupported_501(manager, \"create fact\") from None\n    except ValueError as exc:\n        raise _map_memory_fact_value_error(exc) from exc\n    except (MemoryConflictError, MemoryCorruptionError) as exc:\n        raise _map_memory_manager_error(exc) from exc\n    except OSError as exc:\n        raise HTTPException(status_code=500, detail=\"Failed to create memory fact.\") from exc\n\n    if fact_id is None:\n        # max_facts cap evicted the new (lower-confidence) fact; it was not stored.\n        raise HTTPException(status_code=409, detail=\"Fact was not stored because memory.max_facts kept higher-confidence facts\")\n    return MemoryResponse(**memory_data)\n\n\n@router.delete(\n    \"/memory/facts/{fact_id}\",\n    response_model=MemoryResponse,\n    response_model_exclude_none=True,\n    summary=\"Delete Memory Fact\",\n    description=\"Delete a single saved memory fact by its fact id.\",\n)\nasync def delete_memory_fact_endpoint(fact_id: str, http_request: Request) -> MemoryResponse:\n    \"\"\"Delete a single fact from memory by fact id.\"\"\"\n    manager = await asyncio.to_thread(get_memory_manager)\n    try:","sourceCodeStart":312,"sourceCodeEnd":348,"githubUrl":"https://github.com/bytedance/deer-flow/blob/1dd6ba1acb03700589994b0366c5d1c7d05e2eff/backend/app/gateway/routers/memory.py#L312-L348","documentation":"500 raised when creating a single memory fact hits OSError at the persistence layer. The fact-creation call itself succeeded logically; writing the updated memory store to disk failed with an I/O error (permissions, disk full, lock contention at OS level). Distinct from the 409 cap case and the ValueError validation path.","triggerScenarios":"POST /api/memory/facts while the memory file cannot be written (read-only mount, permission change after startup); disk-full conditions; antivirus/SCIM intercepting the write on the host.","commonSituations":"Memory directory created by root during setup but the Gateway drops privileges afterwards; long-running processes holding the memory file; disk quota exhaustion on shared hosts.","solutions":["Inspect the chained OSError in Gateway logs (path and errno)","Repair write permissions on the memory store path and free disk space","If caused by a second process locking the file, isolate the memory path per Gateway instance","Retry the fact creation after remediation — the write is atomic, so no partial fact is left behind"],"exampleFix":"# before: docker-compose mounts memory volume read-only -> every POST /memory/facts -> 500\n# after\nvolumes:\n  - ./data/memory:/data/memory   # remove :ro flag, ensure ownership matches Gateway user","handlingStrategy":"retry","validationCode":"null","typeGuard":"null","tryCatchPattern":"try { return await createFact(body); } catch (e) { if (e.status === 500 && /Failed to create memory fact/.test(e.detail)) { await delay(backoff(attempt++)); if (attempt <= 2) return createFact(body); } throw e; }","preventionTips":["Monitor disk space and directory permissions on the memory store","Ensure memory volume mounts are writable (no :ro) in container configs","Writes are atomic — a failed create leaves no partial fact, so bounded retry is safe"],"tags":["memory","filesystem","http-500","persistence"],"backgroundTag":null,"analyzedSha":"1dd6ba1acb03700589994b0366c5d1c7d05e2eff","analyzedAt":"2026-08-14T21:20:34.804Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}