{"record":{"id":"f2d8500622ba2fbb","repo":"fullstackhero/dotnet-starter-kit","slug":"group-with-id-command-id-not-found","errorCode":null,"errorMessage":"Group with ID '{command.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/DeleteGroup/DeleteGroupCommandHandler.cs","lineNumber":30,"sourceCode":"{\n    private readonly IdentityDbContext _dbContext;\n    private readonly ICurrentUser _currentUser;\n    private readonly IUserPermissionService _userPermissionService;\n\n    public DeleteGroupCommandHandler(IdentityDbContext dbContext, ICurrentUser currentUser, IUserPermissionService userPermissionService)\n    {\n        _dbContext = dbContext;\n        _currentUser = currentUser;\n        _userPermissionService = userPermissionService;\n    }\n\n    public async ValueTask<Unit> Handle(DeleteGroupCommand command, CancellationToken cancellationToken)\n    {\n        ArgumentNullException.ThrowIfNull(command);\n\n        var group = await _dbContext.Groups\n            .FirstOrDefaultAsync(g => g.Id == command.Id, cancellationToken)\n            ?? throw new NotFoundException($\"Group with ID '{command.Id}' not found.\");\n\n        if (group.IsSystemGroup)\n        {\n            throw new ForbiddenException(\"System groups cannot be deleted.\");\n        }\n\n        // Snapshot members before delete; soft-delete flips IsDeleted but membership rows\n        // persist, so capture first for clarity.\n        var memberIds = await _dbContext.UserGroups\n            .Where(ug => ug.GroupId == command.Id)\n            .Select(ug => ug.UserId)\n            .ToListAsync(cancellationToken);\n\n        // Soft delete via domain method\n        group.Delete(_currentUser.GetUserId().ToString());\n\n        await _dbContext.SaveChangesAsync(cancellationToken);\n","sourceCodeStart":12,"sourceCodeEnd":48,"githubUrl":"https://github.com/fullstackhero/dotnet-starter-kit/blob/3f2959e683e9f83f13e55e1678c9119f63c7e8e5/src/Modules/Identity/Modules.Identity/Features/v1/Groups/DeleteGroup/DeleteGroupCommandHandler.cs#L12-L48","documentation":"Thrown by DeleteGroupCommandHandler when no group with the provided command.Id exists in the tenant-scoped Groups set. This is a not-found guard before deletion: the lookup (optionally with member/role cleanup) found no matching aggregate, so the delete cannot proceed.","triggerScenarios":"DELETE /groups/{id} for an already-deleted group, a nonexistent id, a cross-tenant id, or Guid.Empty.","commonSituations":"Double delete from a retrying client; stale list data after another admin deleted the group; hardcoded ids in scripts.","solutions":["Re-fetch the group list and confirm the id before deleting","Treat 404 on delete as success for idempotent cleanup logic","Fix tenant context/headers if the id exists but under a different tenant"],"exampleFix":"// before\nawait api.DeleteGroup(id); // may 404 on retry\n// after\ntry { await api.DeleteGroup(id); } catch (ApiException e) when (e.Status == 404) { /* already gone */ }","handlingStrategy":"try-catch","validationCode":"var exists = (await api.SearchGroups(name)).Any(g => g.Id == id);\nif (!exists) return; // nothing to delete","typeGuard":null,"tryCatchPattern":"try { await api.DeleteGroup(id); }\ncatch (ApiException e) when (e.Status == 404) { /* idempotent: already deleted */ }","preventionTips":["Treat 404 on delete as success in retries/cleanup jobs","Refresh list data before destructive actions","Keep tenant headers consistent"],"tags":["http-404","identity","groups","delete"],"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"}