{"record":{"id":"983d4f1ab358ccfa","repo":"Budibase/budibase","slug":"app-with-name-name-is-already-taken","errorCode":null,"errorMessage":"App with name '${name}' is already taken.","messagePattern":"App with name '(.+?)' is already taken\\.","errorType":"validation","errorClass":"HTTPError","httpStatus":400,"severity":"error","filePath":"packages/server/src/sdk/workspace/workspaceApps/crud.ts","lineNumber":18,"sourceCode":"import { context, docIds, events, HTTPError } from \"@budibase/backend-core\"\nimport { RequiredKeys, WithoutDocMetadata, WorkspaceApp } from \"@budibase/types\"\nimport sdk from \"../..\"\nimport { helpers } from \"@budibase/shared-core\"\nimport { getValidProjectIdsForDuplication } from \"../projects/utils\"\n\nasync function guardName(name: string, id?: string) {\n  const existingWorkspaceApps = await fetch()\n  const normalizedName = helpers.normalizeForComparison(name)\n\n  if (\n    existingWorkspaceApps.find(\n      app =>\n        helpers.normalizeForComparison(app.name) === normalizedName &&\n        app._id !== id\n    )\n  ) {\n    throw new HTTPError(`App with name '${name}' is already taken.`, 400)\n  }\n}\n\nconst duplicateScreens = async (originalAppId: string, newAppId: string) => {\n  const screens = await sdk.screens.fetch()\n\n  const appScreens = screens.filter(s => s.workspaceAppId === originalAppId)\n  const newScreens = []\n  for (let i = 0; i < appScreens.length; i++) {\n    const screen = appScreens[i]\n    const createdScreen = await sdk.screens.create({\n      ...{\n        layoutId: screen.layoutId,\n        showNavigation: screen.showNavigation,\n        width: screen.width,\n        routing: screen.routing,\n        props: screen.props,\n        name: screen.name,","sourceCodeStart":1,"sourceCodeEnd":36,"githubUrl":"https://github.com/Budibase/budibase/blob/a81a902e9a8fe55b467d106765f6638f12e35c49/packages/server/src/sdk/workspace/workspaceApps/crud.ts#L1-L36","documentation":"guardName enforces unique workspace app names within a workspace, comparing normalized (case/whitespace-insensitive) names. When creating a new workspace app, or renaming one during update, if any other app (different _id) has the same normalized name, a 400 HTTPError is thrown.","triggerScenarios":"Calling sdk.workspaceApps.create with a name matching an existing app; calling update with a name that differs from the persisted name and collides (after normalization) with another app in the same workspace DB.","commonSituations":"Renaming 'Admin' to 'admin' when 'admin' exists; trailing-space or casing variants of an existing name; automation scripts that create workspace apps without checking fetch() first; concurrent creations racing past the uniqueness check.","solutions":["Fetch existing workspace apps (sdk.workspaceApps.fetch()) and pick a unique name before create/rename","Rely on helpers.duplicateName (as duplicate() does) to auto-suffix the name, e.g. 'Admin 2'","Catch the 400 and retry with a suffixed name"],"exampleFix":"// before\nawait sdk.workspaceApps.create({ name: desiredName, url: `/${slug}` })\n// after\nconst existing = await sdk.workspaceApps.fetch()\nconst name = helpers.duplicateName(desiredName, existing.map(a => a.name))\nawait sdk.workspaceApps.create({ name, url: `/${slugify(name)}` })","handlingStrategy":"validation","validationCode":"const existing = await sdk.workspaceApps.fetch()\nconst normalized = name.trim().toLowerCase()\nif (existing.some(a => a.name.trim().toLowerCase() === normalized && a._id !== id)) {\n  throw new Error(`Name '${name}' already in use`)\n}","typeGuard":null,"tryCatchPattern":"try {\n  await sdk.workspaceApps.create(app)\n} catch (e) {\n  if (e?.status === 400 && e?.message?.includes('already taken')) {\n    const names = (await sdk.workspaceApps.fetch()).map(a => a.name)\n    await sdk.workspaceApps.create({ ...app, name: helpers.duplicateName(app.name, names) })\n  } else throw e\n}","preventionTips":["Check existing names (case/whitespace-insensitively) before create/rename","Use helpers.duplicateName for auto-suffixed names","Keep a single code path for workspace app creation to enforce uniqueness"],"tags":["uniqueness-conflict","http-400","workspace-apps"],"backgroundTag":"name-already-taken","analyzedSha":"a81a902e9a8fe55b467d106765f6638f12e35c49","analyzedAt":"2026-08-29T01:03:10.972Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}