{"record":{"id":"fe2a1719020c8196","repo":"bytedance/deer-flow","slug":"agent-normalized-name-already-exists","errorCode":null,"errorMessage":"Agent '{normalized_name}' already exists","messagePattern":"Agent '(.+?)' already exists","errorType":"http","errorClass":"HTTPException","httpStatus":409,"severity":"warning","filePath":"backend/app/gateway/routers/agents.py","lineNumber":344,"sourceCode":"    if request.skills is not None:\n        config_data[\"skills\"] = request.skills\n    # model / model_settings / thinking_enabled / reasoning_effort (issue #4336).\n    _apply_model_behavior(config_data, request)\n\n    store = get_agent_store()\n\n    def _create_agent() -> AgentResponse:\n        # Worker thread: existence checks + persistence (file IO or a DB round\n        # trip) must stay off the event loop.\n        store.create(normalized_name, config_data, request.soul, user_id=user_id)\n        logger.info(\"Created agent '%s'\", normalized_name)\n        agent_cfg = load_agent_config(normalized_name, user_id=user_id)\n        return _agent_config_to_response(agent_cfg, include_soul=True, user_id=user_id)\n\n    try:\n        return await asyncio.to_thread(_create_agent)\n    except AgentExistsError:\n        raise HTTPException(status_code=409, detail=f\"Agent '{normalized_name}' already exists\")\n    except Exception as e:\n        logger.error(f\"Failed to create agent '{request.name}': {e}\", exc_info=True)\n        raise HTTPException(status_code=500, detail=f\"Failed to create agent: {str(e)}\")\n\n\n@router.put(\n    \"/agents/{name}\",\n    response_model=AgentResponse,\n    summary=\"Update Custom Agent\",\n    description=\"Update an existing custom agent's config and/or SOUL.md.\",\n)\nasync def update_agent(name: str, request: AgentUpdateRequest) -> AgentResponse:\n    \"\"\"Update an existing custom agent.\n\n    Args:\n        name: The agent name.\n        request: The update request (all fields optional).\n","sourceCodeStart":326,"sourceCodeEnd":362,"githubUrl":"https://github.com/bytedance/deer-flow/blob/1dd6ba1acb03700589994b0366c5d1c7d05e2eff/backend/app/gateway/routers/agents.py#L326-L362","documentation":"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.","triggerScenarios":"POST `/agents/my-agent` twice; creating 'MyAgent' when 'myagent' exists (normalization makes names case-insensitive); double-clicked submit buttons or retried requests.","commonSituations":"Frontends without disabled-state on submit; retries after network errors that actually succeeded server-side; users assuming names are case-sensitive.","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"],"exampleFix":"# before\nPOST /agents { name: 'summarizer' }  # exists -> 409\n# after\nGET /agents/check?name=summarizer  # taken -> offer update\nPUT /agents/summarizer { ... }","handlingStrategy":"validation","validationCode":"const check = await api.checkAgentName(name); // GET /agents/check\nif (!check.valid || !check.available) {\n  throw new Error(`name taken/invalid: ${name}`);\n}\nawait api.createAgent({ ...body, name });","typeGuard":null,"tryCatchPattern":"try { return await api.createAgent(body); }\ncatch (e) {\n  if (e.status === 409 && /already exists/.test(e.detail)) {\n    return api.updateAgent(body.name.toLowerCase(), body); // upsert semantics\n  }\n  throw e;\n}","preventionTips":["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"],"tags":["http-409","agents","conflict","case-insensitive"],"backgroundTag":null,"analyzedSha":"1dd6ba1acb03700589994b0366c5d1c7d05e2eff","analyzedAt":"2026-08-14T21:20:34.804Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}