bytedance/deer-flow · error · HTTPException
Failed to update agent: {str(e)}
Error message
Failed to update agent: {str(e)} What it means
Catch-all 500 on PUT `/agents/{name}`: any exception during the update pipeline that is not itself an HTTPException — config write failures, SOUL.md write errors, serializer issues, or the post-update re-read failing. Genuine HTTPExceptions (404, 409 legacy, 422 model) are re-raised untouched, so this 500 always means an unexpected storage-layer failure.
Source
Thrown at backend/app/gateway/routers/agents.py:464
# Persist config (when changed) and/or soul (when provided) off the
# event loop. A no-change PATCH commits nothing and re-reads current state.
if updated is not None or request.soul is not None:
await asyncio.to_thread(store.update, name, updated, request.soul, user_id=user_id)
logger.info(f"Updated agent '{name}'")
def _refresh() -> AgentResponse:
# Worker thread: re-read config + SOUL off the event loop.
refreshed_cfg = load_agent_config(name, user_id=user_id)
return _agent_config_to_response(refreshed_cfg, include_soul=True, user_id=user_id)
return await asyncio.to_thread(_refresh)
except HTTPException:
raise
except Exception as e:
logger.error(f"Failed to update agent '{name}': {e}", exc_info=True)
raise HTTPException(status_code=500, detail=f"Failed to update agent: {str(e)}")
class UserProfileResponse(BaseModel):
"""Response model for the global user profile (USER.md)."""
content: str | None = Field(default=None, description="USER.md content, or null if not yet created")
class UserProfileUpdateRequest(BaseModel):
"""Request body for setting the global user profile."""
content: str = Field(default="", description="USER.md content — describes the user's background and preferences")
@router.get(
"/user-profile",
response_model=UserProfileResponse,
summary="Get User Profile",View on GitHub (pinned to 1dd6ba1acb)
Solutions
- Read the logged traceback (`Failed to update agent '<name>'`) to find the failing step
- Fix filesystem permissions/disk issues on the agents directory
- If the config is now corrupt, restore from backup or recreate the agent
- Serialize agent updates in the UI to avoid read-modify-write races
Defensive patterns
Strategy: try-catch
Try / catch
try { return await api.updateAgent(name, body); }
catch (e) {
if (e.status === 500 && /Failed to update agent/.test(e.detail)) {
const fresh = await api.getAgent(name); // verify post-failure state before retry
throw new AgentUpdateFailedError(name, e.detail, fresh);
}
throw e;
} Prevention
- Because update is read-modify-write, re-read the agent after any failure before retrying
- Serialize concurrent edits to the same agent in the UI
- Watch for permission/disk errors in logs when 500s cluster on updates
When it happens
Trigger: Permission denied rewriting config.yaml; disk full writing SOUL.md; concurrent writers corrupting the file between read and write; DB update constraint failure.
Common situations: Long-running servers whose data dir ownership changed; two tabs updating the same agent; partial writes after a crash leaving an unreadable config that then fails the refresh read.
Related errors
- Failed to list agents: {str(e)}
- Failed to get agent: {str(e)}
- Failed to create agent: {str(e)}
- Failed to create memory fact.
- Failed to read user profile: {str(e)}
AI-assisted analysis of bytedance/deer-flow@1dd6ba1acb (2026-08-14).
Data as JSON: /api/errors/18e4fa39afd12a8d.
Report an issue: GitHub.