Skip to content

7.1.1 regression: "Sorry, you are not allowed to give users that role." when Multi-Role Support is enabled and default_role is not in get_editable_roles() #501

Description

@codep0et

7.1.1 regression: "Sorry, you are not allowed to give users that role." when Multi-Role Support is enabled and default_role is not in get_editable_roles()

Summary

AAM 7.1.1 introduced a regression that causes role assignment to fail with:

Sorry, you are not allowed to give users that role.

This affects single-site WordPress installs where Multi-Role Support is enabled and the site's WordPress default role (set via Settings → General) has been filtered out of get_editable_roles() — for example by a theme or plugin using the editable_roles filter.

The error affects all users including administrators, and occurs on both user-edit.php and user-new.php.


Root Cause (with diff evidence)

The change introduced in 7.1.1 is in application/Backend/tmpl/user/multiple-roles.php:

+ <input type="hidden" value="<?php echo esc_js(get_option('default_role')); ?>" name="role" />

This was intended to satisfy wp_ensure_editable_role() (added in WordPress 6.7), which validates that $_POST['role'] is present and corresponds to a role in get_editable_roles().

The problem: the hidden field is hardcoded to get_option('default_role') — typically subscriber — regardless of which role the user actually selected in AAM's aam_user_roles[] multi-select. If the site has filtered subscriber out of get_editable_roles() (a common pattern for sites that don't use built-in WP roles), wp_ensure_editable_role() sees an invalid role and calls wp_die().

Behaviour comparison

AAM 7.1.0 AAM 7.1.1
$_POST['role'] on user-edit.php native WP <select name="role"> (correct role) hidden <input name="role"> hardcoded to get_option('default_role')
$_POST['aam_user_roles[]'] present present
wp_ensure_editable_role() result ✅ passes ❌ fails if default_roleget_editable_roles()

Environment

WordPress version 6.9.4 (reproducible on any 6.7+)
AAM version 7.1.1
Setup Single-site
PHP version 8.x
Multi-Role Support Enabled (AAM → Settings → Core Settings)
Trigger condition Site's default_role is excluded from get_editable_roles()

Steps to Reproduce

  1. Install WordPress (single-site) with AAM 7.1.1
  2. Enable Multiple Roles Support in AAM → Settings → Core Settings
  3. In your theme or a plugin, add a filter that removes the default role from editable roles:
    add_filter('editable_roles', function ($roles) {
        unset($roles['subscriber']); // or whatever get_option('default_role') returns
        return $roles;
    });
  4. Log in as an Administrator
  5. Go to wp-admin/users.php and click Edit on any user
  6. Change the user's role using AAM's role selector
  7. Click Update User

Expected Behaviour

The user's role is updated to the role selected in AAM's multi-role field.

Actual Behaviour

Sorry, you are not allowed to give users that role.

wp_ensure_editable_role() validates $_POST['role'] which AAM 7.1.1 set to get_option('default_role') — a role that is not present in get_editable_roles() on this site.


Suggested Fix

Instead of hardcoding get_option('default_role') in the hidden field, use the first role from aam_user_roles[] — the role the user actually selected:

- <input type="hidden" value="<?php echo esc_js(get_option('default_role')); ?>" name="role" />
+ <input type="hidden" value="<?php echo esc_js(!empty($_GET['aam_user_roles'][0]) ? $_GET['aam_user_roles'][0] : get_option('default_role')); ?>" name="role" />

Or, more robustly, inject it server-side on admin_init so it is always in sync with the user's selection regardless of template rendering order:

add_action('admin_init', function () {
    if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
        return;
    }

    // When AAM's multi-role field is present, always use the first selected
    // role as $_POST['role'] so wp_ensure_editable_role() receives a valid,
    // actually-editable role — not the site's default_role which may have
    // been removed from get_editable_roles() by the site owner.
    if (!isset($_POST['aam_user_roles'])) {
        return;
    }

    $roles = (array) $_POST['aam_user_roles'];

    if (!empty($roles[0])) {
        $role = sanitize_text_field($roles[0]);

        if (get_role($role)) {
            $_POST['role']    = $role;
            $_REQUEST['role'] = $role;
        }
    }
}, 0);

Verification

  • is_admin()YES
  • current_user_can('promote_user', $user_id)YES
  • get_editable_roles() → returns all custom roles correctly (but not subscriber)
  • Deactivating AAM resolves the issue immediately
  • Downgrading to AAM 7.1.0 resolves the issue (native <select name="role"> is used instead)

Related

Metadata

Metadata

Assignees

Labels

Projects

Status
In progress

Relationships

None yet

Development

No branches or pull requests

Issue actions