{"record":{"id":"e497e64ddc185668","repo":"jlcodes99/cockpit-tools","slug":"accounts-groups-error-duplicate","errorCode":"accounts.groups.error.duplicate","errorMessage":"accounts.groups.error.duplicate","messagePattern":"accounts\\.groups\\.error\\.duplicate","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"src/pages/AccountsPage.tsx","lineNumber":2904,"sourceCode":"      })\n    })\n  };\n\n  const handleAssignAccountsToGroup = async (\n    groupId: string,\n    groupName: string,\n    accountIds: string[]\n  ) => {\n    const currentGroup = accountGroups.find((group) => group.id === groupId)\n    if (!currentGroup) return\n\n    const nextName = groupName.trim()\n    if (!nextName) {\n      throw new Error(t('platformLayout.groupNameRequired'))\n    }\n\n    if (accountGroups.some((group) => group.id !== groupId && group.name === nextName)) {\n      throw new Error(t('accounts.groups.error.duplicate'))\n    }\n\n    const currentIds = new Set(currentGroup.accountIds)\n    const nextIds = new Set(accountIds)\n    const addedIds = accountIds.filter((accountId) => !currentIds.has(accountId))\n    const removedIds = currentGroup.accountIds.filter((accountId) => !nextIds.has(accountId))\n    const shouldRename = nextName !== currentGroup.name\n\n    if (!shouldRename && addedIds.length === 0 && removedIds.length === 0) return\n\n    if (shouldRename) {\n      await renameGroup(groupId, nextName)\n    }\n\n    if (accountIds.length > 0) {\n      await assignAccountsToGroup(groupId, accountIds)\n    }\n","sourceCodeStart":2886,"sourceCodeEnd":2922,"githubUrl":"https://github.com/jlcodes99/cockpit-tools/blob/1ed8b77992d62ca81fabf744deb0839ad361d5bf/src/pages/AccountsPage.tsx#L2886-L2922","documentation":"The account-group rename handler checks that no OTHER group (group.id !== groupId) already uses the trimmed target name; if one does, it throws an Error with the localized message 'accounts.groups.error.duplicate'. It enforces unique group names within the accounts page.","triggerScenarios":"Calling the group rename handler with a nextName that exactly matches the current name of a different account group in accountGroups.","commonSituations":"User types a name that already exists in the group list; bulk-importing group definitions with repeated names; renaming a group to the name of a previously deleted-but-still-present group.","solutions":["Choose a group name that is not already used by another group.","Before calling the handler, check accountGroups.some(g => g.id !== groupId && g.name === nextName) and surface a duplicate-name message.","Catch the error in the UI and display the localized duplicate-name message next to the input."],"exampleFix":"// before\nawait controller.renameGroup(groupId, 'Work');\n// after\nconst nextName = name.trim();\nif (accountGroups.some(g => g.id !== groupId && g.name === nextName)) {\n  showError(t('accounts.groups.error.duplicate'));\n  return;\n}\nawait controller.renameGroup(groupId, nextName);","handlingStrategy":"validation","validationCode":"const nextName = groupName.trim();\nconst isDuplicate = accountGroups.some(g => g.id !== groupId && g.name === nextName);\nif (isDuplicate) throw new Error(t('accounts.groups.error.duplicate'));","typeGuard":null,"tryCatchPattern":"try {\n  await controller.renameGroup(groupId, groupName);\n} catch (e) {\n  if (e.message === t('accounts.groups.error.duplicate')) {\n    showFieldError('groupName', e.message);\n    return;\n  }\n  throw e;\n}","preventionTips":["Check name uniqueness against all sibling groups before submit.","Show existing group names near the input so users avoid collisions.","Treat group names case-sensitively/insensitively consistently with the controller's comparison."],"tags":["validation","duplicate","ui"],"backgroundTag":"duplicate-name-conflict","analyzedSha":"1ed8b77992d62ca81fabf744deb0839ad361d5bf","analyzedAt":"2026-09-05T09:51:41.178Z","contentChangedAt":"2026-09-05T09:51:41.178Z","schemaVersion":2},"datasetVersion":"2026-09-12T12:17:11.808Z"}