fullstackhero/dotnet-starter-kit · error · NotFoundException
Group with ID ' ' not found.
Error message
Group with ID '{id}' not found. What it means
GetGroupAsync queries Groups (including GroupRoles) by Id and, when no row matches, throws this NotFoundException. It is the guard at the top of UpdateGroupCommandHandler.Handle — no update proceeds if the group ID does not exist in the database.
Solutions
- Verify the group ID is correct and exists: query the group list endpoint or the Groups table for that tenant before updating.
- Refresh the client's cached group list and remove entries for deleted groups.
- Confirm the request is hitting the correct tenant — tenant-scoped DbContext filters hide groups belonging to other tenants.
Example fix
// before
await mediator.Send(new UpdateGroupCommand { Id = idFromStaleCache, Name = newName });
// after
var group = await groupApi.GetByIdAsync(idFromStaleCache);
if (group is null)
{
await groupListRefetch(); // drop stale entry
return;
}
await mediator.Send(new UpdateGroupCommand { Id = group.Id, Name = newName }); Defensive patterns
Strategy: validation
Validate before calling
var exists = await groupApi.ExistsAsync(id); // or GetByIdAsync != null
if (!exists)
{
await refreshGroupList(); // drop stale cache entry
return;
} Type guard
Group? tryGetGroup(IEnumerable<Group> groups, Guid id) => groups.FirstOrDefault(g => g.Id == id);
Try / catch
try
{
await mediator.Send(new UpdateGroupCommand { Id = id, /* ... */ });
}
catch (NotFoundException)
{
// group vanished (deleted or different tenant): refresh list and inform the user
await refreshGroupList();
notify("This group no longer exists.");
} Prevention
- Always fetch the group immediately before updating instead of trusting cached IDs.
- Include tenant context checks when copying IDs between environments or tenants.
- Revalidate IDs after bulk delete operations in admin tooling.
When it happens
Trigger: Sending UpdateGroupCommand with an Id that does not exist in the Groups table (already deleted, wrong tenant, typo/GUID from another environment).
Common situations: Stale frontend cache showing a group that was deleted by another admin; copying an ID from logs of a different tenant (tenant isolation filters the row out); pasting a group ID from a dev database into a staging environment.
Understand the failure class
Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.
Related errors
- Roles not found
- Group with ID ' ' not found.
- Group with name ' ' already exists.
- Group with ID ' ' not found.
- Group with ID ' ' not found.
AI-assisted analysis of fullstackhero/dotnet-starter-kit@3f2959e683 (2026-09-15).
Data as JSON: /api/errors/5dbc1cad46a1222c.
Report an issue: GitHub.
Appendix: source
Thrown at src/Modules/Identity/Modules.Identity/Features/v1/Groups/UpdateGroup/UpdateGroupCommandHandler.cs:72
var memberIds = await _dbContext.UserGroups
.Where(ug => ug.GroupId == command.Id)
.Select(ug => ug.UserId)
.ToListAsync(cancellationToken);
foreach (var memberId in memberIds)
{
await _userPermissionService.InvalidatePermissionCacheAsync(memberId, cancellationToken).ConfigureAwait(false);
}
}
return await BuildResponseAsync(group, newRoleIds, cancellationToken);
}
private async Task<Group> GetGroupAsync(Guid id, CancellationToken cancellationToken)
{
return await _dbContext.Groups
.Include(g => g.GroupRoles)
.FirstOrDefaultAsync(g => g.Id == id, cancellationToken)
?? throw new NotFoundException($"Group with ID '{id}' not found.");
}
private async Task ValidateUniqueNameAsync(Guid excludeId, string name, CancellationToken cancellationToken)
{
var nameExists = await _dbContext.Groups
.AnyAsync(g => g.Name == name && g.Id != excludeId, cancellationToken);
if (nameExists)
{
throw new CustomException($"Group with name '{name}' already exists.", (IEnumerable<string>?)null, System.Net.HttpStatusCode.Conflict);
}
}
private async Task ValidateRoleIdsAsync(IReadOnlyList<string>? roleIds, CancellationToken cancellationToken)
{
if (roleIds is not { Count: > 0 })
{
return;View on GitHub (pinned to 3f2959e683)