fullstackhero/dotnet-starter-kit · error · NotFoundException

Group with ID ' ' not found.

Error message

Group with ID '{query.Id}' not found.

What it means

Thrown by GetGroupByIdQueryHandler when the no-tracking query (including GroupRoles) for query.Id returns null. It means no group with that ID exists (or is invisible under the tenant filter), so the read model cannot be built.

Solutions

  1. Verify the id exists via the groups list endpoint
  2. Handle 404 in the UI by navigating back / showing 'group not found'
  3. Re-check tenant headers if the group exists in another tenant

Example fix

// before
var group = await api.GetGroupById(routeId); // crashes on 404
// after
try { var group = await api.GetGroupById(routeId); }
catch (ApiException e) when (e.Status == 404) { navigate('/groups'); }
Defensive patterns

Strategy: try-catch

Validate before calling

const guidRe = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
if (!guidRe.test(routeId)) navigate('/groups');

Type guard

const isValidGroupId = (v: string | undefined): v is string => !!v && guidRe.test(v);

Try / catch

try { return await api.GetGroupById(id); }
catch (e) { if (is404(e)) { showNotFound(); return null; } throw e; }

Prevention

When it happens

Trigger: GET /groups/{id} with a nonexistent, deleted, cross-tenant, or malformed id.

Common situations: Bookmark/deep-link to a deleted group; stale client cache after deletion; unit tests reusing random Guids.

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


AI-assisted analysis of fullstackhero/dotnet-starter-kit@3f2959e683 (2026-09-15). Data as JSON: /api/errors/f8916b6f93303623. Report an issue: GitHub.

Appendix: source

Thrown at src/Modules/Identity/Modules.Identity/Features/v1/Groups/GetGroupById/GetGroupByIdQueryHandler.cs:25

namespace FSH.Modules.Identity.Features.v1.Groups.GetGroupById;

public sealed class GetGroupByIdQueryHandler : IQueryHandler<GetGroupByIdQuery, GroupDto>
{
    private readonly IdentityDbContext _dbContext;

    public GetGroupByIdQueryHandler(IdentityDbContext dbContext)
    {
        _dbContext = dbContext;
    }

    public async ValueTask<GroupDto> Handle(GetGroupByIdQuery query, CancellationToken cancellationToken)
    {
        var group = await _dbContext.Groups
            .AsNoTracking()
            .Include(g => g.GroupRoles)
            .FirstOrDefaultAsync(g => g.Id == query.Id, cancellationToken)
            ?? throw new NotFoundException($"Group with ID '{query.Id}' not found.");

        var memberCount = await _dbContext.UserGroups
            .AsNoTracking()
            .CountAsync(ug => ug.GroupId == group.Id, cancellationToken);

        var roleIds = group.GroupRoles.Select(gr => gr.RoleId).ToList();
        var roleNames = roleIds.Count > 0
            ? await _dbContext.Roles
                .AsNoTracking()
                .Where(r => roleIds.Contains(r.Id))
                .Select(r => r.Name!)
                .ToListAsync(cancellationToken)
            : [];

        return new GroupDto
        {
            Id = group.Id,
            Name = group.Name,

View on GitHub (pinned to 3f2959e683)