bytedance/deer-flow · error · HTTPException
Agent '{name}' only exists in the legacy shared layout and i
Error message
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. What it means
409 on DELETE `/agents/{name}`: the store returned outcome 'legacy' — the agent exists only in the legacy shared layout, not scoped to the deleting user. Deletion is blocked because removing a shared-layout agent would affect all users; the operator must migrate first. Same legacy-layout concept as the PUT-side 409, resolved by the same script.
Source
Thrown at backend/app/gateway/routers/agents.py:562
Raises:
HTTPException: 404 if no per-user copy exists; 409 if only a legacy
shared copy exists (suggesting the migration script).
"""
_require_agents_api_enabled()
_validate_agent_name(name)
name = _normalize_agent_name(name)
user_id = get_effective_user_id()
store = get_agent_store()
try:
# Off the event loop: file rmtree or a DB delete plus memory cleanup.
outcome = await asyncio.to_thread(store.delete, name, user_id=user_id)
except Exception as e:
logger.error(f"Failed to delete agent '{name}': {e}", exc_info=True)
raise HTTPException(status_code=500, detail=f"Failed to delete agent: {str(e)}")
if outcome == "legacy":
raise HTTPException(
status_code=409,
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."),
)
if outcome == "missing":
raise HTTPException(status_code=404, detail=f"Agent '{name}' not found")
if outcome == "not-custom-agent":
raise HTTPException(
status_code=409,
detail=(f"Directory for '{name}' contains memory data but is not a custom agent because config.yaml is missing; it was preserved."),
)
logger.info(f"Deleted agent '{name}'")
View on GitHub (pinned to 1dd6ba1acb)
Solutions
- Run `scripts/migrate_user_isolation.py` to move legacy agents into per-user scope, then delete the migrated copy
- Alternatively remove the legacy shared agent manually with operator intent (it is shared — deleting it affects everyone)
- Re-run the delete and expect 204 on success
Example fix
# before DELETE /agents/legacy-agent # 409 # after python scripts/migrate_user_isolation.py DELETE /agents/legacy-agent # 204
Defensive patterns
Strategy: try-catch
Try / catch
try { await api.deleteAgent(name); }
catch (e) {
if (e.status === 409 && /legacy shared layout/.test(e.detail)) {
showAdminNotice('Run scripts/migrate_user_isolation.py first; this agent is shared');
return;
}
throw e;
} Prevention
- Treat legacy-layout 409 as an operations task, not a user error — surface it to admins
- Deleting a shared agent affects all users; always route through the migration script
- Include the migration script in upgrade runbooks before enabling delete flows
When it happens
Trigger: Deleting a pre-isolation shared agent on an upgraded file-backend deployment; admin cleanup scripts walking old agent names.
Common situations: Post-upgrade housekeeping hitting 409 on every legacy agent; mixed layouts after partial migration.
Related errors
- Agent '{name}' only exists in the legacy shared layout and i
- Agent '{normalized_name}' already exists
- Failed to delete agent: {str(e)}
- Directory for '{name}' contains memory data but is not a cus
- Failed to update agent: ${res.statusText}
AI-assisted analysis of bytedance/deer-flow@1dd6ba1acb (2026-08-14).
Data as JSON: /api/errors/5bfa3c54dac9b792.
Report an issue: GitHub.