{"record":{"id":"95f61e5a440f72eb","repo":"Budibase/budibase","slug":"agent-with-name-name-already-exists","errorCode":null,"errorMessage":"Agent with name '${name}' already exists.","messagePattern":"Agent with name '(.+?)' already exists\\.","errorType":"http","errorClass":"HTTPError","httpStatus":400,"severity":"error","filePath":"packages/server/src/sdk/workspace/ai/agents/crud.ts","lineNumber":113,"sourceCode":"    .map(row => row.doc)\n    .filter((doc): doc is DeprecatedAgent => !!doc)\n}\n\nconst guardName = async (name: string, id?: string) => {\n  if (!name.trim()) {\n    throw new HTTPError(NAME_REQUIRED_ERROR, 400)\n  }\n\n  const agents = await fetchRaw()\n  const normalizedName = helpers.normalizeForComparison(name)\n  const duplicate = agents.find(\n    agent =>\n      helpers.normalizeForComparison(agent.name) === normalizedName &&\n      agent._id !== id\n  )\n\n  if (duplicate) {\n    throw new HTTPError(`Agent with name '${name}' already exists.`, 400)\n  }\n}\n\nconst encodeSecret = (value?: string): string | undefined => {\n  if (!value || value.startsWith(SECRET_ENCODING_PREFIX)) {\n    return value\n  }\n  return `${SECRET_ENCODING_PREFIX}${encryption.encrypt(value)}`\n}\n\nconst decodeSecret = (value?: string): string | undefined => {\n  if (!value || !value.startsWith(SECRET_ENCODING_PREFIX)) {\n    return value\n  }\n  return encryption.decrypt(value.slice(SECRET_ENCODING_PREFIX.length))\n}\n\nconst encodeSlackIntegrationSecrets = (","sourceCodeStart":95,"sourceCodeEnd":131,"githubUrl":"https://github.com/Budibase/budibase/blob/a81a902e9a8fe55b467d106765f6638f12e35c49/packages/server/src/sdk/workspace/ai/agents/crud.ts#L95-L131","documentation":"guardName enforces unique agent names within a workspace. It compares normalizeForComparison(name) of the incoming name against all existing agents and, if another agent (different _id) matches case/whitespace-insensitively, throws a 400 HTTPError with this message naming the conflicting name.","triggerScenarios":"Creating an agent whose name matches an existing one, or updating an agent to a name already used by a different agent (id !== existing _id). Matching is normalized, so \"VPN Agent\" collides with \"vpn agent\" or \"  VPN  Agent \".","commonSituations":"Users renaming an agent to a name that already exists; duplicate imports/seed scripts creating the same agent twice; UI not pre-checking uniqueness; case-only renames where the user thinks they are renaming but the API treats it as a duplicate of another agent, or vice versa when renaming an agent to its own name is fine (same _id passes).","solutions":["Pick a unique name — check the existing agents list and adjust","For renames that only change casing/spacing of the agent's own name, this is allowed (its own _id is excluded from the duplicate check); verify you are not accidentally targeting another agent's _id","Pre-check uniqueness client-side using normalizeForComparison-equivalent logic before submitting","Catch the 400 HTTPError and show the server message ('Agent with name ... already exists') in the UI"],"exampleFix":"// before\nawait sdk.ai.agents.create({ name: \"Support Agent\" }) // may 400\n// after\nconst existing = await sdk.ai.agents.fetch()\nif (existing.some(a => a.name.trim().toLowerCase() === \"support agent\")) {\n  name = \"Support Agent 2\"\n}\nawait sdk.ai.agents.create({ name })","handlingStrategy":"validation","validationCode":"const agents = await sdk.ai.agents.fetch()\nconst normalized = name.trim().toLowerCase()\nif (agents.some(a => a.name.trim().toLowerCase() === normalized && a._id !== id)) {\n  throw new Error(`Agent with name '${name}' already exists.`)\n}","typeGuard":null,"tryCatchPattern":"try {\n  await sdk.ai.agents.update({ ...agent, name })\n} catch (err) {\n  if (err instanceof HTTPError && err.status === 400 && /already exists/.test(err.message)) {\n    // prompt the user for a different name\n  } else { throw err }\n}","preventionTips":["Pre-check name uniqueness (normalized) in the UI before submitting","Remember matching is case/whitespace-insensitive","Handle the 400 in form error state with the server message"],"tags":["validation","duplicate","http-400","crud"],"backgroundTag":"duplicate-name-conflict","analyzedSha":"a81a902e9a8fe55b467d106765f6638f12e35c49","analyzedAt":"2026-08-29T01:03:10.972Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}