{"record":{"id":"2c01f42ed596308e","repo":"jlcodes99/cockpit-tools","slug":"platformlayout-groupnamerequired","errorCode":"platformLayout.groupNameRequired","errorMessage":"platformLayout.groupNameRequired","messagePattern":"platformLayout\\.groupNameRequired","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"src/pages/AccountsPage.tsx","lineNumber":2900,"sourceCode":"    setShowTagModal(null);\n    window.requestAnimationFrame(() => {\n      window.requestAnimationFrame(() => {\n        window.scrollTo({ top: scrollY, behavior: 'auto' })\n      })\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","sourceCodeStart":2882,"sourceCodeEnd":2918,"githubUrl":"https://github.com/jlcodes99/cockpit-tools/blob/1ed8b77992d62ca81fabf744deb0839ad361d5bf/src/pages/AccountsPage.tsx#L2882-L2918","documentation":"When renaming an account group in the Accounts page, the controller trims the submitted name and rejects an empty result by throwing an Error whose message is the localized string 'platformLayout.groupNameRequired'. The i18n key doubles as the error code; the UI is expected to surface it to the user as 'group name is required'.","triggerScenarios":"Calling the account-group rename handler (inside useAccountsPageController) with a groupName that is empty or consists only of whitespace after trim().","commonSituations":"User clears the group name input and confirms the rename dialog; a form submits with an unvalidated empty text field; a script/automation invokes the controller directly with ''.","solutions":["Populate the groupName field before submitting the rename (disable the confirm button while the input is empty).","Validate on the caller side: trim the name and bail out early if it is falsy before invoking the handler.","Catch the error in the calling controller/UI and show the localized validation message instead of letting it propagate."],"exampleFix":"// before\nawait controller.renameGroup(groupId, nameInput.value);\n// after\nconst name = nameInput.value.trim();\nif (!name) return; // or show validation message\nawait controller.renameGroup(groupId, name);","handlingStrategy":"validation","validationCode":"const name = groupName.trim();\nif (!name) throw new Error(t('platformLayout.groupNameRequired'));","typeGuard":"const hasGroupName = (v: unknown): v is string =>\n  typeof v === 'string' && v.trim().length > 0;","tryCatchPattern":"try {\n  await controller.renameGroup(groupId, groupName);\n} catch (e) {\n  if (e.message === t('platformLayout.groupNameRequired')) {\n    showFieldError('groupName', e.message);\n    return;\n  }\n  throw e;\n}","preventionTips":["Disable the rename confirm button while the trimmed input is empty.","Trim names at form-submit boundaries, not just at display time.","Run a shared required-field validator before calling the controller."],"tags":["validation","ui","i18n"],"backgroundTag":"empty-required-field","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"}