Certificate template duplicate name error (#46414)

**Related issue:** Resolves #44821

# Checklist for submitter

If some of the following don't apply, delete the relevant line.

- [x] Changes file added for user-visible changes in `changes/`,
`orbit/changes/` or `ee/fleetd-chrome/changes`.
See [Changes
files](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/guides/committing-changes.md#changes-files)
for more information.

## Testing

- [x] QA'd all new/changed functionality manually



<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Bug Fixes**
* Fixed inline validation to show duplicate certificate name errors even
when the conflicting certificate is on a different page.
* Improved server-side error handling during certificate creation to
better detect name conflicts and present clearer, focused feedback on
the Name field.

<!-- review_stack_entry_start -->

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/46414?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)

<!-- review_stack_entry_end -->
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
Konstantin Sykulev
2026-06-01 10:01:47 -05:00
committed by GitHub
parent 698c99dd00
commit f619655a61
2 changed files with 14 additions and 3 deletions
+1
View File
@@ -0,0 +1 @@
- Fixed inline error for duplicate certificate name not showing when the conflicting certificate is on a different page.
@@ -58,9 +58,9 @@ const AddCertModal = ({
subjectAlternativeName: "",
});
// Server-side validation errors keyed by form field; cleared when the user
// edits the corresponding input. Today only SAN can come back with a
// field-targeted 422; other fields fall through to the generic flash.
// edits the corresponding input.
const [serverErrors, setServerErrors] = useState<{
name?: string;
subjectAlternativeName?: string;
}>({});
@@ -102,6 +102,9 @@ const AddCertModal = ({
const onInputChange = (update: { name: string; value: string }) => {
const updatedFormData = { ...formData, [update.name]: update.value };
setFormData(updatedFormData);
if (update.name === "name" && serverErrors.name) {
setServerErrors((prev) => ({ ...prev, name: undefined }));
}
if (
update.name === "subjectAlternativeName" &&
serverErrors.subjectAlternativeName
@@ -145,8 +148,15 @@ const AddCertModal = ({
const sanReason = getErrorReason(e, {
nameEquals: "subject_alternative_name",
});
const nameConflict = getErrorReason(e, {
reasonIncludes: "already exists",
});
if (sanReason) {
setServerErrors({ subjectAlternativeName: sanReason });
} else if (nameConflict) {
setServerErrors({
name: "Name is already used by another certificate.",
});
} else {
renderFlash("error", "Couldn't add certificate. Please try again.");
}
@@ -170,7 +180,7 @@ const AddCertModal = ({
label="Name"
value={formData.name}
onChange={onInputChange}
error={formValidation.name?.message}
error={serverErrors.name ?? formValidation.name?.message}
helpText="Letters, numbers, spaces, dashes, and underscores only. Name can be used as certificate alias to reference in configuration profiles."
parseTarget
placeholder="VPN certificate"