fullstackhero/dotnet-starter-kit · error · CustomException
Group with name ' ' already exists.
Error message
Group with name '{command.Name}' already exists. What it means
CreateGroup enforces group-name uniqueness within the tenant; when a Group with command.Name already exists it throws CustomException with HttpStatusCode.Conflict (HTTP 409). Unlike NotFound/Forbidden, this surfaces as a 409 with the message in the response body.
Solutions
- Query existing groups first and reuse the group if the name matches (idempotent create)
- Catch the 409 and surface 'name already in use' in the UI to let the user pick another name
- Uniquify the name (e.g. suffix) in seeding/import scripts
Example fix
// before
await api.CreateGroup(new CreateGroupCommand { Name = "Admins" });
// after
var existing = await api.SearchGroups("Admins");
var group = existing.FirstOrDefault() ?? await api.CreateGroup(new CreateGroupCommand { Name = "Admins" }); Defensive patterns
Strategy: try-catch
Validate before calling
var clash = (await api.SearchGroups(name)).Any(g => g.Name.Equals(name, StringComparison.Ordinal));
if (clash) throw new InvalidOperationException("Group name already in use"); Try / catch
try { await api.CreateGroup(cmd); }
catch (ApiException e) when (e.Status == 409) { NotifyUser("A group with that name already exists."); } Prevention
- Make create-group idempotent: search first, create only if absent
- Guard seeding scripts against double execution
- Uniquify names in import jobs
When it happens
Trigger: POST /groups with a Name identical to an existing group in the same tenant (exact string match).
Common situations: Double-submitting a create form; seeding scripts run twice; re-running an import that creates default groups.
Related errors
- Group with name ' ' already exists.
- A product with SKU ' ' already exists.
- A product with name ' ' already exists.
- Another product with name
- A brand with name ' ' already exists.
AI-assisted analysis of fullstackhero/dotnet-starter-kit@3f2959e683 (2026-09-15).
Data as JSON: /api/errors/5adb398bcb640d91.
Report an issue: GitHub.
Appendix: source
Thrown at src/Modules/Identity/Modules.Identity/Features/v1/Groups/CreateGroup/CreateGroupCommandHandler.cs:33
private readonly ICurrentUser _currentUser;
public CreateGroupCommandHandler(IdentityDbContext dbContext, ICurrentUser currentUser)
{
_dbContext = dbContext;
_currentUser = currentUser;
}
public async ValueTask<GroupDto> Handle(CreateGroupCommand command, CancellationToken cancellationToken)
{
ArgumentNullException.ThrowIfNull(command);
// Validate name is unique within tenant
var nameExists = await _dbContext.Groups
.AnyAsync(g => g.Name == command.Name, cancellationToken);
if (nameExists)
{
throw new CustomException($"Group with name '{command.Name}' already exists.", (IEnumerable<string>?)null, System.Net.HttpStatusCode.Conflict);
}
// Validate role IDs exist — fetch Id+Name in a single query to avoid a second roundtrip later
List<(string Id, string Name)> resolvedRoles = [];
if (command.RoleIds is { Count: > 0 })
{
var rawRoles = await _dbContext.Roles
.Where(r => command.RoleIds.Contains(r.Id))
.Select(r => new { r.Id, r.Name })
.ToListAsync(cancellationToken);
resolvedRoles = rawRoles.Select(r => (r.Id, r.Name!)).ToList();
var invalidRoleIds = command.RoleIds.Except(resolvedRoles.Select(r => r.Id)).ToList();
if (invalidRoleIds.Count > 0)
{
throw new NotFoundException($"Roles not found: {string.Join(", ", invalidRoleIds)}");
}
}View on GitHub (pinned to 3f2959e683)