fullstackhero/dotnet-starter-kit · error · NotFoundException

role not found

Error message

role not found

What it means

Generic sentinel thrown in RoleService when a role lookup by identifier fails. In the GetRoleAsync path it means FindByIdAsync returned no FshRole for the supplied id — the caller referenced a role that does not exist in this tenant's role store.

Solutions

  1. Verify the role id exists (query AspNetRoles / roles list endpoint) before calling
  2. Fix the source of the stale id — re-fetch the role list after deletions
  3. Confirm you are connected to the correct database/tenant

Example fix

// before
var role = await roleService.GetRoleAsync(deletedId);
// after
var roles = await roleService.ListAsync(ct);
if (!roles.Any(r => r.Id == id)) return Results.NotFound();
var role = await roleService.GetRoleAsync(id, ct);
Defensive patterns

Strategy: try-catch

Validate before calling

var exists = (await roleService.ListAllAsync(ct)).Any(r => r.Id == id);
if (!exists) return Results.NotFound($"Role {id} not found");

Type guard

public static bool RoleExists(RoleDto? role) => role is not null && !string.IsNullOrEmpty(role.Id);

Try / catch

try { var role = await roleService.GetRoleAsync(id, ct); }
catch (NotFoundException ex) { return Results.NotFound(new { ex.Message, RoleId = id }); }

Prevention

When it happens

Trigger: Calling GetRoleAsync with an id that was deleted, a typo'd/truncated role id, or an id from a different tenant/database.

Common situations: Stale cached role ids in the frontend after a role was deleted; passing a permission or claim id instead of a role id; querying the wrong environment's database.

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/e9a403dab6708c42. Report an issue: GitHub.

Appendix: source

Thrown at src/Modules/Identity/Modules.Identity/Features/v1/Roles/RoleService.cs:100

            .Select(r => new RoleDto { Id = r.Id, Name = r.Name!, Description = r.Description })
            .ToListAsync(cancellationToken)
            .ConfigureAwait(false);

        return new PagedResponse<RoleDto>
        {
            Items = rows,
            PageNumber = page,
            PageSize = size,
            TotalCount = total,
            TotalPages = (int)Math.Ceiling(total / (double)size),
        };
    }

    public async Task<RoleDto?> GetRoleAsync(string id, CancellationToken cancellationToken = default)
    {
        FshRole? role = await roleManager.FindByIdAsync(id);

        _ = role ?? throw new NotFoundException("role not found");

        return new RoleDto { Id = role.Id, Name = role.Name!, Description = role.Description };
    }

    public async Task<RoleDto> CreateOrUpdateRoleAsync(string roleId, string name, string description, CancellationToken cancellationToken = default)
    {
        FshRole? role = string.IsNullOrEmpty(roleId)
            ? null
            : await roleManager.FindByIdAsync(roleId);

        if (role != null)
        {
            // System roles cannot be modified — neither renamed nor re-described.
            EnsureNotSystemRole(role.Name, "System roles cannot be modified.");
            // And no custom role can be renamed to a system role's name.
            EnsureNotSystemRole(name, "Cannot rename a role to a system role's name.");

            role.Name = name;

View on GitHub (pinned to 3f2959e683)