{"record":{"id":"6733f1c4d8760a29","repo":"fullstackhero/dotnet-starter-kit","slug":"group-with-name-name-already-exists","errorCode":null,"errorMessage":"Group with name '{name}' already exists.","messagePattern":"Group with name '(.+?)' already exists\\.","errorType":"exception","errorClass":"CustomException","httpStatus":409,"severity":"error","filePath":"src/Modules/Identity/Modules.Identity/Features/v1/Groups/UpdateGroup/UpdateGroupCommandHandler.cs","lineNumber":82,"sourceCode":"        return await BuildResponseAsync(group, newRoleIds, cancellationToken);\n    }\n\n    private async Task<Group> GetGroupAsync(Guid id, CancellationToken cancellationToken)\n    {\n        return await _dbContext.Groups\n            .Include(g => g.GroupRoles)\n            .FirstOrDefaultAsync(g => g.Id == id, cancellationToken)\n            ?? throw new NotFoundException($\"Group with ID '{id}' not found.\");\n    }\n\n    private async Task ValidateUniqueNameAsync(Guid excludeId, string name, CancellationToken cancellationToken)\n    {\n        var nameExists = await _dbContext.Groups\n            .AnyAsync(g => g.Name == name && g.Id != excludeId, cancellationToken);\n\n        if (nameExists)\n        {\n            throw new CustomException($\"Group with name '{name}' already exists.\", (IEnumerable<string>?)null, System.Net.HttpStatusCode.Conflict);\n        }\n    }\n\n    private async Task ValidateRoleIdsAsync(IReadOnlyList<string>? roleIds, CancellationToken cancellationToken)\n    {\n        if (roleIds is not { Count: > 0 })\n        {\n            return;\n        }\n\n        var existingRoleIds = await _dbContext.Roles\n            .Where(r => roleIds.Contains(r.Id))\n            .Select(r => r.Id)\n            .ToListAsync(cancellationToken);\n\n        var invalidRoleIds = roleIds.Except(existingRoleIds).ToList();\n        if (invalidRoleIds.Count > 0)\n        {","sourceCodeStart":64,"sourceCodeEnd":100,"githubUrl":"https://github.com/fullstackhero/dotnet-starter-kit/blob/3f2959e683e9f83f13e55e1678c9119f63c7e8e5/src/Modules/Identity/Modules.Identity/Features/v1/Groups/UpdateGroup/UpdateGroupCommandHandler.cs#L64-L100","documentation":"ValidateUniqueNameAsync checks whether another group (Id != excludeId) already has the requested Name and, if so, throws CustomException with HTTP 409 Conflict. Group names are unique within the store, so a rename to an existing name is rejected.","triggerScenarios":"Sending UpdateGroupCommand whose Name matches a different existing group in the same tenant — typically a rename colliding with an already-taken group name.","commonSituations":"Two admins concurrently rename groups to the same value; a UI that doesn't pre-check name availability; renaming a group back to a name it previously held before being renamed away while another group took it.","solutions":["Choose a different, unique group name for the update.","Add a client-side uniqueness check (list groups, compare names case-insensitively) before submitting the update.","If the name should be free but isn't, find the group holding it and rename/delete that group first, or merge the two groups."],"exampleFix":"// before\nawait mediator.Send(new UpdateGroupCommand { Id = id, Name = \"Sales\" }); // 409: 'Sales' exists\n\n// after\nvar groups = await groupApi.ListAsync();\nif (groups.Any(g => g.Name.Equals(\"Sales\", StringComparison.OrdinalIgnoreCase) && g.Id != id))\n{\n    showValidationError(\"A group named 'Sales' already exists.\");\n    return;\n}\nawait mediator.Send(new UpdateGroupCommand { Id = id, Name = \"Sales\" });","handlingStrategy":"validation","validationCode":"var taken = (await groupApi.ListAsync())\n    .Any(g => g.Name.Trim().Equals(newName.Trim(), StringComparison.OrdinalIgnoreCase) && g.Id != groupId);\nif (taken) showValidationError(\"Group name already in use.\");","typeGuard":"bool isUniqueName(IEnumerable<Group> groups, string name, Guid excludeId) =>\n    !groups.Any(g => g.Id != excludeId && string.Equals(g.Name, name, StringComparison.OrdinalIgnoreCase));","tryCatchPattern":"try\n{\n    await mediator.Send(new UpdateGroupCommand { Id = id, Name = newName });\n}\ncatch (CustomException ex) when (ex.StatusCode == HttpStatusCode.Conflict)\n{\n    showValidationError(\"A group with that name already exists. Choose another name.\");\n}","preventionTips":["Check name availability client-side before submit and show inline validation.","Trim/normalize names consistently on both client and server.","Guard against concurrent renames by re-checking after any long editing session."],"tags":["identity","groups","conflict","duplicate"],"backgroundTag":"resource-already-exists","analyzedSha":"3f2959e683e9f83f13e55e1678c9119f63c7e8e5","analyzedAt":"2026-09-15T22:20:53.684Z","contentChangedAt":"2026-09-15T22:20:53.684Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}