{"record":{"id":"fd282b23f6658cc9","repo":"bytedance/deer-flow","slug":"memory-fact-fact-id-not-found","errorCode":null,"errorMessage":"Memory fact '{fact_id}' not found.","messagePattern":"Memory fact '(.+?)' not found\\.","errorType":"http","errorClass":"HTTPException","httpStatus":404,"severity":"warning","filePath":"backend/app/gateway/routers/memory.py","lineNumber":353,"sourceCode":"    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:\n        memory_data = await asyncio.to_thread(manager.delete_fact, fact_id, user_id=_resolve_memory_user_id(http_request))\n    except NotImplementedError:\n        raise _unsupported_501(manager, \"delete fact\") from None\n    except KeyError as exc:\n        raise HTTPException(status_code=404, detail=f\"Memory fact '{fact_id}' not found.\") 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 delete memory fact.\") from exc\n\n    return MemoryResponse(**memory_data)\n\n\n@router.patch(\n    \"/memory/facts/{fact_id}\",\n    response_model=MemoryResponse,\n    response_model_exclude_none=True,\n    summary=\"Patch Memory Fact\",\n    description=\"Partially update a single saved memory fact by its fact id while preserving omitted fields.\",\n)\nasync def update_memory_fact_endpoint(fact_id: str, request: FactPatchRequest, http_request: Request) -> MemoryResponse:\n    \"\"\"Partially update a single fact manually.\"\"\"\n    manager = await asyncio.to_thread(get_memory_manager)","sourceCodeStart":335,"sourceCodeEnd":371,"githubUrl":"https://github.com/bytedance/deer-flow/blob/1dd6ba1acb03700589994b0366c5d1c7d05e2eff/backend/app/gateway/routers/memory.py#L335-L371","documentation":"404 raised when delete_fact raises KeyError: no fact with the given fact_id exists for the resolved user. Memory is per-user isolated (_resolve_memory_user_id), so a fact id that exists for another user is equally 'not found'.","triggerScenarios":"DELETE /api/memory/facts/{fact_id} with an id from an outdated UI list; deleting a fact already removed by a concurrent request or by the agent itself; sending a fact id belonging to a different user; malformed id strings that never match stored keys.","commonSituations":"Stale frontend lists after background memory maintenance; double-click delete firing two requests; id copy errors (truncated UUIDs); switching authenticated users while reusing cached fact ids.","solutions":["Re-fetch the current fact list (GET /api/memory) and delete using a fresh id","Treat 404 on delete as success if the goal is the fact being gone (idempotent delete handling)","Confirm the request carries the same user identity that created the fact"],"exampleFix":"// before\nawait fetch(`/api/memory/facts/${id}`, {method:'DELETE'}).then(r => { if (!r.ok) throw new Error('delete failed'); });\n// after\nconst res = await fetch(`/api/memory/facts/${id}`, {method:'DELETE'});\nif (res.status === 404) { console.info('fact already removed'); return; }\nif (!res.ok) throw new Error('delete failed');","handlingStrategy":"try-catch","validationCode":"const mem = await getMemory(); if (!mem.facts?.[factId]) { console.info('fact already absent'); return; } // proceed to DELETE","typeGuard":"function factExists(factId: string, memory: {facts?: Record<string, unknown>}): boolean { return Boolean(memory.facts && factId in memory.facts); }","tryCatchPattern":"try { await deleteFact(id); } catch (e) { if (e.status === 404) return; /* already gone — treat as success */ throw e; }","preventionTips":["Handle delete-404 as success (idempotent delete semantics)","Refresh the fact list before offering delete actions in the UI","Debounce double-clicks on delete buttons to avoid duplicate requests"],"tags":["memory","http-404","idempotency"],"backgroundTag":null,"analyzedSha":"1dd6ba1acb03700589994b0366c5d1c7d05e2eff","analyzedAt":"2026-08-14T21:20:34.804Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}