OrchardCMS/OrchardCore · error · InvalidOperationException
Role does not exist.
Error message
Role {normalizedRoleName} does not exist. What it means
Thrown by UserStore.AddToRoleAsync when the requested normalized role name does not match any role returned by IRoleService.GetRoleNamesAsync(). The store refuses to attach a role that does not exist in the system, so the user is not modified.
Solutions
- Create the role first (via IRoleService or RoleManager) before assigning it to users.
- Verify the exact role name and its normalization (NormalizeKey uses culture-invariant lowercase); pass the same normalized value users see.
- Check for typos or renamed roles and update the calling code or seed data.
- Wrap in try-catch for InvalidOperationException to fail gracefully with a clear message.
Example fix
// before
await _userManager.AddToRoleAsync(user, "Adimn");
// after
if (!await _roleManager.RoleExistsAsync("Admin")) { await _roleManager.CreateAsync(new Role { RoleName = "Admin" }); }
await _userManager.AddToRoleAsync(user, "Admin"); Defensive patterns
Strategy: validation
Validate before calling
var roleNames = await _roleService.GetRoleNamesAsync(); bool exists = roleNames.Any(r => string.Equals(r, roleName, StringComparison.OrdinalIgnoreCase));
Type guard
bool RoleExists(IEnumerable<string> roles, string name) => roles?.Any(r => string.Equals(r, name, StringComparison.OrdinalIgnoreCase)) == true;
Try / catch
try { await _userManager.AddToRoleAsync(user, roleName); }
catch (InvalidOperationException ex) when (ex.Message.Contains("does not exist"))
{ _logger.LogWarning("Role {Role} missing", roleName); } Prevention
- Create all roles before assigning users (recipe order: roles step before users step)
- Normalize role names consistently (invariant lowercase)
- Centralize role-name constants instead of inline strings
- Validate role names when importing/migrating users
When it happens
Trigger: Calling UserManager.AddToRoleAsync(user, roleName) with a role name that is misspelled, has wrong casing after normalization, or was never created.
Common situations: Seeding users before roles are created in a recipe/migration; renaming a role while code still references the old name; case-sensitivity mismatches between code and the role definition.
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
- Provider is already linked for
- Couldn't generate a unique user id. Too many attempts.
- The name cannot be null or empty.
- The value cannot be null or empty.
- code cannot be null or empty.
AI-assisted analysis of OrchardCMS/OrchardCore@4306c0717f (2026-09-13).
Data as JSON: /api/errors/32713589f961ebb3.
Report an issue: GitHub.
Appendix: source
Thrown at src/OrchardCore/OrchardCore.Users.Core/Services/UserStore.cs:411
return Task.CompletedTask;
}
#endregion IUserEmailStore<IUser>
#region IUserRoleStore<IUser>
public async Task AddToRoleAsync(IUser user, string normalizedRoleName, CancellationToken cancellationToken)
{
ArgumentNullException.ThrowIfNull(user);
if (user is User u)
{
var roleNames = await _roleService.GetRoleNamesAsync();
var roleName = roleNames.FirstOrDefault(r => NormalizeKey(r) == normalizedRoleName);
if (string.IsNullOrEmpty(roleName))
{
throw new InvalidOperationException($"Role {normalizedRoleName} does not exist.");
}
u.RoleNames.Add(roleName);
}
}
public async Task RemoveFromRoleAsync(IUser user, string normalizedRoleName, CancellationToken cancellationToken)
{
ArgumentNullException.ThrowIfNull(user);
if (user is User u)
{
var roleNames = await _roleService.GetRoleNamesAsync();
var roleName = roleNames.FirstOrDefault(r => NormalizeKey(r) == normalizedRoleName);
if (string.IsNullOrEmpty(roleName))
{
throw new InvalidOperationException($"Role {normalizedRoleName} does not exist.");View on GitHub (pinned to 4306c0717f)