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

  1. Create the role first (via IRoleService or RoleManager) before assigning it to users.
  2. Verify the exact role name and its normalization (NormalizeKey uses culture-invariant lowercase); pass the same normalized value users see.
  3. Check for typos or renamed roles and update the calling code or seed data.
  4. 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

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


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)