Budibase/budibase · error · HTTPError

A custom REST template named "${name.trim()}" already exists

Error message

A custom REST template named "${name.trim()}" already exists

What it means

A 409 HTTPError thrown when a template with the same kebab-cased name already exists, detected by scanning the workspace's existing templates via fetch(). This is the name-uniqueness check performed before generating the new template id.

Source

Thrown at packages/server/src/sdk/workspace/restTemplates.ts:102

const createWithoutLock = async ({
  name,
  description,
  data,
  fileExtension,
  operationsCount,
}: CreateCustomRestTemplateParams): Promise<RestTemplate> => {
  const db = context.getWorkspaceDB()
  const normalizedName = kebabCase(name)
  if (!normalizedName) {
    throw new HTTPError("Template name must contain letters or numbers", 400)
  }

  const existingTemplate = (await fetch()).find(
    template => kebabCase(template.name) === normalizedName
  )
  if (existingTemplate) {
    throw new HTTPError(
      `A custom REST template named "${name.trim()}" already exists`,
      409
    )
  }

  const restTemplateId = dbCore.generateRestTemplateID()
  const existing = await db.tryGet<CustomRestTemplateDocument>(restTemplateId)
  if (existing) {
    throw new HTTPError(
      `A custom REST template named "${name.trim()}" already exists`,
      409
    )
  }

  const folder = getObjectStoreFolder(restTemplateId)
  const objectStoreKey = `${folder}/openapi.${fileExtension}`
  const document: CustomRestTemplateDocument = {
    _id: restTemplateId,

View on GitHub (pinned to a81a902e9a)

Solutions

  1. Check the returned 409 and surface 'name already in use' to the user, prompting for a new name
  2. Pre-check with fetch() (list templates) and compare kebabCase(name) before creating
  3. Append a distinguishing suffix (version, timestamp) to guarantee uniqueness
  4. Deduplicate concurrent submissions by disabling the create action once in flight

Example fix

// before
await restTemplates.create({ name: "My API" }) // 409 if "my-api" exists
// after
const exists = (await restTemplates.fetch()).some(t => kebabCase(t.name) === "my-api")
if (!exists) await restTemplates.create({ name: "My API" })
Defensive patterns

Strategy: validation

Validate before calling

const taken = (await restTemplates.fetch()).some(t => kebabCase(t.name) === kebabCase(name))
if (taken) throw new Error(`A template named "${name}" already exists`)

Type guard

null

Try / catch

try {
  await restTemplates.create({ name })
} catch (e) {
  if (e?.status === 409) {
    // prompt the user for a different name
    return
  }
  throw e
}

Prevention

When it happens

Trigger: Calling create with a name whose kebabCase form equals an existing template's kebabCased name — including names differing only in case, spacing, or separators ("My Template" vs "my-template"), or the exact same create call submitted twice.

Common situations: User clicks 'Create' twice quickly; duplicating a template in the UI without renaming; two workspace admins creating identically named templates concurrently; kebab-case collisions like "REST v2" and "rest-v2".

Related errors


AI-assisted analysis of Budibase/budibase@a81a902e9a (2026-08-29). Data as JSON: /api/errors/75ec665c8a06214d. Report an issue: GitHub.