bytedance/deer-flow · warning · HTTPException
Agent '{normalized_name}' already exists
Error message
Agent '{normalized_name}' already exists What it means
409 from POST `/agents`: the store raised `AgentExistsError` during `create` — a config for the (lowercased) name already exists in the current user's scope. Creation is an atomic check-and-write in the store, so racing creates also surface here.
Source
Thrown at backend/app/gateway/routers/agents.py:344
if request.skills is not None:
config_data["skills"] = request.skills
# model / model_settings / thinking_enabled / reasoning_effort (issue #4336).
_apply_model_behavior(config_data, request)
store = get_agent_store()
def _create_agent() -> AgentResponse:
# Worker thread: existence checks + persistence (file IO or a DB round
# trip) must stay off the event loop.
store.create(normalized_name, config_data, request.soul, user_id=user_id)
logger.info("Created agent '%s'", normalized_name)
agent_cfg = load_agent_config(normalized_name, user_id=user_id)
return _agent_config_to_response(agent_cfg, include_soul=True, user_id=user_id)
try:
return await asyncio.to_thread(_create_agent)
except AgentExistsError:
raise HTTPException(status_code=409, detail=f"Agent '{normalized_name}' already exists")
except Exception as e:
logger.error(f"Failed to create agent '{request.name}': {e}", exc_info=True)
raise HTTPException(status_code=500, detail=f"Failed to create agent: {str(e)}")
@router.put(
"/agents/{name}",
response_model=AgentResponse,
summary="Update Custom Agent",
description="Update an existing custom agent's config and/or SOUL.md.",
)
async def update_agent(name: str, request: AgentUpdateRequest) -> AgentResponse:
"""Update an existing custom agent.
Args:
name: The agent name.
request: The update request (all fields optional).
View on GitHub (pinned to 1dd6ba1acb)
Solutions
- Pick a different name, or PUT to update the existing agent instead of POSTing a duplicate
- Pre-check with GET `/agents/check` (case-insensitive availability) before showing the create button
- Guard the UI submit button against double clicks
Example fix
# before
POST /agents { name: 'summarizer' } # exists -> 409
# after
GET /agents/check?name=summarizer # taken -> offer update
PUT /agents/summarizer { ... } Defensive patterns
Strategy: validation
Validate before calling
const check = await api.checkAgentName(name); // GET /agents/check
if (!check.valid || !check.available) {
throw new Error(`name taken/invalid: ${name}`);
}
await api.createAgent({ ...body, name }); Try / catch
try { return await api.createAgent(body); }
catch (e) {
if (e.status === 409 && /already exists/.test(e.detail)) {
return api.updateAgent(body.name.toLowerCase(), body); // upsert semantics
}
throw e;
} Prevention
- Check name availability before enabling the create button
- Remember names are case-insensitive after normalization
- Disable submit during in-flight create to avoid double-POST races
When it happens
Trigger: POST `/agents/my-agent` twice; creating 'MyAgent' when 'myagent' exists (normalization makes names case-insensitive); double-clicked submit buttons or retried requests.
Common situations: Frontends without disabled-state on submit; retries after network errors that actually succeeded server-side; users assuming names are case-sensitive.
Related errors
- Agent '{name}' only exists in the legacy shared layout and i
- Agent '{name}' only exists in the legacy shared layout and i
- Directory for '{name}' contains memory data but is not a cus
- Branching is only available in the main conversation.
- Thread has a run in flight. Set the goal after the run finis
AI-assisted analysis of bytedance/deer-flow@1dd6ba1acb (2026-08-14).
Data as JSON: /api/errors/fe2a1719020c8196.
Report an issue: GitHub.