{"record":{"id":"fc7c256d659e7b27","repo":"Budibase/budibase","slug":"group-name-name-is-unavailable","errorCode":null,"errorMessage":"Group name \"${name}\" is unavailable","messagePattern":"Group name \"(.+?)\" is unavailable","errorType":"http","errorClass":"GroupNameUnavailableError","httpStatus":409,"severity":"error","filePath":"packages/pro/src/sdk/groups/groups.ts","lineNumber":210,"sourceCode":"export async function getBulk(\n  ids: string[],\n  opts: { enriched: false }\n): Promise<UserGroup[]>\nexport async function getBulk(\n  ids: string[],\n  opts?: { enriched?: boolean }\n): Promise<UserGroup[]>\nexport async function getBulk(\n  ids: string[],\n  opts: { enriched?: boolean } = { enriched: true }\n): Promise<UserGroup[] | EnrichedUserGroup[]> {\n  return db.groups.getBulk(ids, opts as { enriched: true })\n}\n\nasync function guardNameAvailability(name: string) {\n  const existingGroup = await db.groups.getByName(name)\n  if (existingGroup) {\n    throw new GroupNameUnavailableError(name)\n  }\n}\n\nasync function getCreatorsCountInGroup(group: UserGroup) {\n  let usersInGroup = await db.groups.getGroupUsers(group._id!)\n  if (!usersInGroup.length) {\n    return 0\n  }\n\n  const globalDb = tenancy.getGlobalDB()\n\n  const users = await globalDb.getMultiple<User>(usersInGroup.map(u => u._id))\n  const creatorsInGroup = await userUtils.creatorsInList(users)\n\n  return creatorsInGroup.filter(x => x).length\n}\n\nfunction isCreatorGroup(group: Pick<UserGroup, \"roles\">) {","sourceCodeStart":192,"sourceCodeEnd":228,"githubUrl":"https://github.com/Budibase/budibase/blob/a81a902e9a8fe55b467d106765f6638f12e35c49/packages/pro/src/sdk/groups/groups.ts#L192-L228","documentation":"When saving a user group, guardNameAvailability checks db.groups.getByName(name) and throws GroupNameUnavailableError if a group with that name already exists. Group names must be unique per tenant, so saving a new group (or renaming) with a taken name is rejected. The message names the conflicting name so the user can pick another.","triggerScenarios":"Calling save() for a group whose name matches an existing group's name (case-sensitive lookup via getByName), including renaming a group to a name already used by another group.","commonSituations":"Two admins creating similarly-named groups concurrently; API-driven group provisioning that retries after a timeout and re-submits the same name; migrating groups from another system without checking for collisions; trailing-whitespace duplicates that still collide after normalization.","solutions":["Check name availability first via the groups name lookup, then save with a unique name.","Retry with a different/qualified name (e.g. append team or environment suffix).","Catch GroupNameUnavailableError in the save flow and surface a friendly 'name in use' validation message.","If the name belongs to a deleted group that still exists in the index, clean up stale group docs/index entries."],"exampleFix":"// before\nawait groups.save({ name: \"Engineering\", roles: {...} })\n// after\nconst existing = await db.groups.getByName(\"Engineering\")\nif (!existing) {\n  await groups.save({ name: \"Engineering\", roles: {...} })\n} else {\n  throw new ValidationError(\"Group name already in use\")\n}","handlingStrategy":"try-catch","validationCode":"const existing = await db.groups.getByName(proposedName)\nif (existing) { /* reject or pick another name before save */ }","typeGuard":null,"tryCatchPattern":"try {\n  await groups.save({ name, roles })\n} catch (err) {\n  if (err instanceof GroupNameUnavailableError) {\n    // surface 'name already in use' and suggest an alternative\n  } else throw err\n}","preventionTips":["Check name availability before save, especially for automated provisioning","Make idempotent group creation: look up by name first, reuse if found","Normalize (trim/case) names consistently to reduce accidental collisions"],"tags":["groups","uniqueness","conflict","validation"],"backgroundTag":"duplicate-resource-name","analyzedSha":"a81a902e9a8fe55b467d106765f6638f12e35c49","analyzedAt":"2026-08-29T01:03:10.972Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}