fullstackhero/dotnet-starter-kit · error · NotFoundException
Role store not configured. Ensure .AddRoles
Error message
Role store not configured. Ensure .AddRoles<FshRole>() and EF stores.
What it means
RoleService.GetRolesAsync checks that roleManager.Roles (the IQueryable from the role store) is not null. A null queryable means Identity was registered without a role store (no .AddRoles<FshRole>() with EF stores backing it), so the service throws NotFoundException('Role store not configured. Ensure .AddRoles<FshRole>() and EF stores.').
Solutions
- Ensure the IdentityBuilder chain includes .AddRoles<FshRole>() before .AddEntityFrameworkStores<TContext>()
- Verify the EF identity stores are registered with the module's DbContext
- Check for custom RoleManager/store registrations that may shadow the EF store
Example fix
// before
services.AddIdentity<FshUser, FshRole>()
.AddEntityFrameworkStores<IdentityDbContext>();
// after
services.AddIdentity<FshUser, FshRole>()
.AddRoles<FshRole>()
.AddEntityFrameworkStores<IdentityDbContext>(); Defensive patterns
Strategy: validation
Validate before calling
// startup check
using var scope = app.Services.CreateScope();
var rm = scope.ServiceProvider.GetRequiredService<RoleManager<FshRole>>();
if (rm.Roles is null) throw new InvalidOperationException('Role store missing: add .AddRoles<FshRole>() with EF stores'); Type guard
bool RoleStoreConfigured(RoleManager<FshRole>? rm) => rm?.Roles is not null;
Try / catch
try { var roles = await roleService.GetRolesAsync(1, 20); }
catch (Exception e) when (e.Message.Contains("Role store not configured")) { logger.LogError(e, "Identity role store misconfigured"); throw; } Prevention
- Keep .AddRoles<FshRole>() in the IdentityBuilder chain
- Add a health/startup check asserting RoleManager.Roles is queryable
- Copy Identity registration from a known-good module config when in doubt
- Cover role listing in an integration test that fails on misconfiguration
When it happens
Trigger: Calling the roles list endpoint on an Identity registration that omitted AddRoles<FshRole>() or the EF role store, causing RoleManager.Roles to be null.
Common situations: Trimmed-down Identity setup copied from a minimal sample (users only, no roles); swapping to a custom role store that returns null Roles; a module registration refactor that dropped AddRoles from the IdentityBuilder chain.
Understand the failure class
Background: "not installed", "pip install", "required for": how missing-dependency errors surface across open-source libraries — this error's family across 34 libraries.
Related errors
- Roles not found
- Roles not found
- role not found
- System role permissions are managed by the framework and…
- operation failed
AI-assisted analysis of fullstackhero/dotnet-starter-kit@3f2959e683 (2026-09-15).
Data as JSON: /api/errors/4928334e3142fbd9.
Report an issue: GitHub.
Appendix: source
Thrown at src/Modules/Identity/Modules.Identity/Features/v1/Roles/RoleService.cs:63
.ToListAsync(cancellationToken);
foreach (var userId in directUserIds.Concat(groupUserIds).Distinct())
{
await userPermissionService.InvalidatePermissionCacheAsync(userId, cancellationToken).ConfigureAwait(false);
}
}
public async Task<PagedResponse<RoleDto>> GetRolesAsync(
int pageNumber = 1,
int pageSize = 20,
string? search = null,
CancellationToken cancellationToken = default)
{
if (roleManager is null)
throw new NotFoundException("RoleManager<FshRole> not resolved. Check Identity registration.");
if (roleManager.Roles is null)
throw new NotFoundException("Role store not configured. Ensure .AddRoles<FshRole>() and EF stores.");
var page = Math.Max(1, pageNumber);
var size = Math.Clamp(pageSize, 1, 200);
var query = roleManager.Roles.AsNoTracking();
if (!string.IsNullOrWhiteSpace(search))
{
var needle = search.Trim().ToLowerInvariant();
query = query.Where(r =>
(r.Name != null && r.Name.ToLower().Contains(needle))
|| (r.Description != null && r.Description.ToLower().Contains(needle)));
}
var total = await query.LongCountAsync(cancellationToken).ConfigureAwait(false);
var rows = await query
.OrderBy(r => r.Name)
.Skip((page - 1) * size)
.Take(size)View on GitHub (pinned to 3f2959e683)