Budibase/budibase · error · HTTPError
App with name '${name}' is already taken.
Error message
App with name '${name}' is already taken. What it means
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.
Source
Thrown at packages/server/src/sdk/workspace/workspaceApps/crud.ts:18
import { context, docIds, events, HTTPError } from "@budibase/backend-core"
import { RequiredKeys, WithoutDocMetadata, WorkspaceApp } from "@budibase/types"
import sdk from "../.."
import { helpers } from "@budibase/shared-core"
import { getValidProjectIdsForDuplication } from "../projects/utils"
async function guardName(name: string, id?: string) {
const existingWorkspaceApps = await fetch()
const normalizedName = helpers.normalizeForComparison(name)
if (
existingWorkspaceApps.find(
app =>
helpers.normalizeForComparison(app.name) === normalizedName &&
app._id !== id
)
) {
throw new HTTPError(`App with name '${name}' is already taken.`, 400)
}
}
const duplicateScreens = async (originalAppId: string, newAppId: string) => {
const screens = await sdk.screens.fetch()
const appScreens = screens.filter(s => s.workspaceAppId === originalAppId)
const newScreens = []
for (let i = 0; i < appScreens.length; i++) {
const screen = appScreens[i]
const createdScreen = await sdk.screens.create({
...{
layoutId: screen.layoutId,
showNavigation: screen.showNavigation,
width: screen.width,
routing: screen.routing,
props: screen.props,
name: screen.name,View on GitHub (pinned to a81a902e9a)
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
Example fix
// before
await sdk.workspaceApps.create({ name: desiredName, url: `/${slug}` })
// after
const existing = await sdk.workspaceApps.fetch()
const name = helpers.duplicateName(desiredName, existing.map(a => a.name))
await sdk.workspaceApps.create({ name, url: `/${slugify(name)}` }) Defensive patterns
Strategy: validation
Validate before calling
const existing = await sdk.workspaceApps.fetch()
const normalized = name.trim().toLowerCase()
if (existing.some(a => a.name.trim().toLowerCase() === normalized && a._id !== id)) {
throw new Error(`Name '${name}' already in use`)
} Try / catch
try {
await sdk.workspaceApps.create(app)
} catch (e) {
if (e?.status === 400 && e?.message?.includes('already taken')) {
const names = (await sdk.workspaceApps.fetch()).map(a => a.name)
await sdk.workspaceApps.create({ ...app, name: helpers.duplicateName(app.name, names) })
} else throw e
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- App not found with id "${workspaceApp._id}"
- Workspace app not found ${workspaceAppId}
- Invalid bookmark query
- Invalid limit query
- Limit query must be between 1 and 100
AI-assisted analysis of Budibase/budibase@a81a902e9a (2026-08-29).
Data as JSON: /api/errors/983d4f1ab358ccfa.
Report an issue: GitHub.