{"record":{"id":"5dbc1cad46a1222c","repo":"fullstackhero/dotnet-starter-kit","slug":"group-with-id-id-not-found","errorCode":null,"errorMessage":"Group with ID '{id}' not found.","messagePattern":"Group with ID '(.+?)' not found\\.","errorType":"exception","errorClass":"NotFoundException","httpStatus":404,"severity":"error","filePath":"src/Modules/Identity/Modules.Identity/Features/v1/Groups/UpdateGroup/UpdateGroupCommandHandler.cs","lineNumber":72,"sourceCode":"            var memberIds = await _dbContext.UserGroups\n                .Where(ug => ug.GroupId == command.Id)\n                .Select(ug => ug.UserId)\n                .ToListAsync(cancellationToken);\n            foreach (var memberId in memberIds)\n            {\n                await _userPermissionService.InvalidatePermissionCacheAsync(memberId, cancellationToken).ConfigureAwait(false);\n            }\n        }\n\n        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;","sourceCodeStart":54,"sourceCodeEnd":90,"githubUrl":"https://github.com/fullstackhero/dotnet-starter-kit/blob/3f2959e683e9f83f13e55e1678c9119f63c7e8e5/src/Modules/Identity/Modules.Identity/Features/v1/Groups/UpdateGroup/UpdateGroupCommandHandler.cs#L54-L90","documentation":"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.","triggerScenarios":"Sending UpdateGroupCommand with an Id that does not exist in the Groups table (already deleted, wrong tenant, typo/GUID from another environment).","commonSituations":"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.","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."],"exampleFix":"// before\nawait mediator.Send(new UpdateGroupCommand { Id = idFromStaleCache, Name = newName });\n\n// after\nvar group = await groupApi.GetByIdAsync(idFromStaleCache);\nif (group is null)\n{\n    await groupListRefetch(); // drop stale entry\n    return;\n}\nawait mediator.Send(new UpdateGroupCommand { Id = group.Id, Name = newName });","handlingStrategy":"validation","validationCode":"var exists = await groupApi.ExistsAsync(id); // or GetByIdAsync != null\nif (!exists)\n{\n    await refreshGroupList(); // drop stale cache entry\n    return;\n}","typeGuard":"Group? tryGetGroup(IEnumerable<Group> groups, Guid id) => groups.FirstOrDefault(g => g.Id == id);","tryCatchPattern":"try\n{\n    await mediator.Send(new UpdateGroupCommand { Id = id, /* ... */ });\n}\ncatch (NotFoundException)\n{\n    // group vanished (deleted or different tenant): refresh list and inform the user\n    await refreshGroupList();\n    notify(\"This group no longer exists.\");\n}","preventionTips":["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."],"tags":["identity","groups","not-found"],"backgroundTag":"entity-not-found","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"}