{"record":{"id":"fb6d128fccb03efd","repo":"bytedance/deer-flow","slug":"directory-for-name-contains-memory-data-but-is","errorCode":null,"errorMessage":"Directory for '{name}' contains memory data but is not a custom agent because config.yaml is missing; it was preserved.","messagePattern":"Directory for '(.+?)' contains memory data but is not a custom agent because config\\.yaml is missing; it was preserved\\.","errorType":"http","errorClass":"HTTPException","httpStatus":409,"severity":"warning","filePath":"backend/app/gateway/routers/agents.py","lineNumber":569,"sourceCode":"    user_id = get_effective_user_id()\n    store = get_agent_store()\n\n    try:\n        # Off the event loop: file rmtree or a DB delete plus memory cleanup.\n        outcome = await asyncio.to_thread(store.delete, name, user_id=user_id)\n    except Exception as e:\n        logger.error(f\"Failed to delete agent '{name}': {e}\", exc_info=True)\n        raise HTTPException(status_code=500, detail=f\"Failed to delete agent: {str(e)}\")\n\n    if outcome == \"legacy\":\n        raise HTTPException(\n            status_code=409,\n            detail=(f\"Agent '{name}' only exists in the legacy shared layout and is not scoped to a user. Run scripts/migrate_user_isolation.py to move legacy agents into the per-user layout before deleting.\"),\n        )\n    if outcome == \"missing\":\n        raise HTTPException(status_code=404, detail=f\"Agent '{name}' not found\")\n    if outcome == \"not-custom-agent\":\n        raise HTTPException(\n            status_code=409,\n            detail=(f\"Directory for '{name}' contains memory data but is not a custom agent because config.yaml is missing; it was preserved.\"),\n        )\n\n    logger.info(f\"Deleted agent '{name}'\")\n","sourceCodeStart":551,"sourceCodeEnd":575,"githubUrl":"https://github.com/bytedance/deer-flow/blob/1dd6ba1acb03700589994b0366c5d1c7d05e2eff/backend/app/gateway/routers/agents.py#L551-L575","documentation":"HTTP 409 returned by DELETE /api/agents/{name} when the store returns 'not-custom-agent': the per-user directory for that agent exists but has no config.yaml, so it only holds memory/facts data. The delete is deliberately refused because rmtree would destroy the user's memory (regression #4279, guarded at persistence/agents/file.py:169-173).","triggerScenarios":"DELETE /api/agents/{name} where users/{user_id}/agents/{name}/ exists but config.yaml is missing — e.g. memory was written for a built-in/non-custom agent, a config.yaml was manually deleted, or a partially failed create left the directory without config.","commonSituations":"Agents that accrued memory data without ever being custom agents, operators who manually pruned config.yaml from the data dir, crashed/interrupted agent creation, or upgrades that changed the agent layout so config.yaml resolution moved.","solutions":["Inspect users/{user_id}/agents/{name}/ under DEER_FLOW_HOME (default backend/.deer-flow) and decide whether the memory data is disposable","If the agent really should be a custom agent, restore/create config.yaml in that directory, then retry the delete","If the memory must be kept, move the directory aside manually (backup) and retry once the guard no longer applies","Report to the user instead of auto-deleting — the 409 exists to preserve data"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"# Check the on-disk condition the guard keys on before calling delete\nfrom pathlib import Path\nagent_dir = Path(home) / \"users\" / user_id / \"agents\" / name\nif agent_dir.exists() and not (agent_dir / \"config.yaml\").is_file():\n    print(f\"'{name}' holds memory data without config.yaml; delete will be refused with 409\")","typeGuard":null,"tryCatchPattern":"try:\n    await client.delete(f\"/api/agents/{name}\")\nexcept httpx.HTTPStatusError as e:\n    if e.response.status_code == 409 and \"not a custom agent\" in e.response.text:\n        # memory-bearing directory; ask the operator, do not force\n        raise RuntimeError(f\"agent '{name}' holds memory data; handle manually\")\n    raise","preventionTips":["Never blind-rmtree agent directories in scripts — always go through the API so the memory guard applies","Back up users/{user_id}/agents/{name} before manual cleanup","When creating agents programmatically, confirm the create call succeeded so half-written directories are not left behind","Surfaces 409 detail text to the operator; it names the exact remedy"],"tags":["api","agents","data-preservation","http-409","memory"],"backgroundTag":null,"analyzedSha":"1dd6ba1acb03700589994b0366c5d1c7d05e2eff","analyzedAt":"2026-08-14T21:20:34.804Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}