"Sorry, you are not allowed to access this page" means WordPress loaded, recognised your login, and then decided your user cannot open this particular admin screen. On a single site it comes from one line in wp-admin/includes/menu.php, a wp_die() with HTTP status 403 that runs when user_can_access_admin_page() returns false.
That narrows the causes to three, and the page you see it on tells you which one: a plugin page that is no longer registered, a capability your role lacks, or a user with no role WordPress recognises at all.
We read the guides that currently rank for this error before writing. Kinsta's knowledge base article (updated 2026-03-11), Themeisle's (updated 2023-09-18) and The Plus Addons' (updated 2026-06-16) each run to over 2,000 words.
All three recommend resetting file permissions, upgrading PHP and replacing .htaccess. None of them mentions the 403, the function that makes the decision, the user_roles option, or the most common harmless case: a bookmarked ?page= link to a plugin that is no longer active.
What the message actually tells you
WordPress has to be running, with your session cookie accepted, to print this sentence. That rules out a whole family of fixes before you start.
A server that refuses to read a file because of permissions returns its own 403 page, from Apache or nginx, without WordPress's wording.
A PHP version too old for a plugin produces a fatal error or the "critical error" screen. An .htaccess problem produces a 500 or a redirect loop.
None of those can reach menu.php and print a polite sentence about access. If you are reading this exact message, the server, PHP and the rewrite rules all worked.
What failed is a decision WordPress made about your user and this screen. The check lives in user_can_access_admin_page() (wp-admin/includes/plugin.php), and it compares the screen against the admin menu that was just built for your capabilities.
Read the URL first: the three causes
Where the message appears is the fastest diagnostic you have.
| Where you see it | Most likely cause | First check |
|---|---|---|
One URL containing admin.php?page= |
The plugin that registered that page is not loaded | wp plugin list --status=inactive |
| One core screen, while the Dashboard works | Your role lacks the capability for that screen | wp user list-caps <id> |
| Every admin screen, including the Dashboard | Your user has no role WordPress recognises | wp db prefix and the capabilities meta key |
A ?page= link to a plugin that is not loaded
Plugin settings screens live at admin.php?page=<slug>. In WordPress 7.1, user_can_access_admin_page() looks up the page's hook name in the $_registered_pages global and returns false if it is missing (verified in the 7.1 branch of wordpress-develop).
So when the plugin is deactivated, its folder was renamed, or it failed to load, the old URL produces the access message even for a full administrator. A bookmark, a link in an old admin notice, or a "Settings" link in an email all trigger it.
This is the one case where nothing is wrong with your account. Reactivate the plugin or stop using the link.
The development branch fixes the confusion.
Trunk adds wp_admin_page_exists() and a wp_admin_page_not_found action marked @since 7.2.0, and returns a 404 "The requested page does not exist." for an unregistered page instead (verified in wordpress-develop trunk on 2026-10-29).
Until that ships in a release, a missing plugin page and a real permission failure print the same sentence.
A core screen your role cannot open
If the Dashboard loads but one screen refuses, the menu entry for that screen requires a capability your user does not have. Each admin menu item is registered with a capability, and user_can_access_admin_page() ends by calling current_user_can() against it.
For an Author trying to open Plugins, that is WordPress working as designed. For someone who believes they are an administrator, the usual causes are a role editor plugin that removed capabilities from the administrator role, or a plugin filtering capabilities through user_has_cap or map_meta_cap.
On multisite there is a second source.
The Network Admin screens print the same sentence from their own checks: wp-admin/network/index.php requires manage_network and network/sites.php requires manage_sites (verified in the WordPress 7.1.4 release). A site administrator who is not a super admin sees it there by design.
Our post on WordPress network admin covers who gets those capabilities.
Every screen, including the Dashboard
The Dashboard menu item requires only read, the most basic capability every built-in role has. If even /wp-admin/ refuses you, your user effectively has no role.
WordPress stores a user's roles in user meta under <prefix>capabilities, and the role definitions in an option called <prefix>user_roles. Both key names are built at runtime from the configured table prefix: WP_User sets cap_key from $wpdb->get_blog_prefix(), and WP_Roles does the same for role_key.
Three things break that chain:
- The prefix changed. After a migration or a prefix change,
$table_prefixinwp-config.phpisabc_but the rows are still calledwp_capabilitiesandwp_user_roles. WordPress looks for keys that do not exist. - The role no longer exists.
WP_User::get_role_caps()keeps only the entries for which$wp_roles->is_role()is true. A user assigned a role that was deleted fromuser_rolesgets no capabilities from it. - The
user_rolesoption is damaged. It is a serialized PHP array. A search-and-replace that changed string lengths without updating the serialized lengths leaves an option that will not unserialize, and every role disappears at once.
Our post on testing a table prefix change covers the first cause in depth, and checking serialized data covers the third.
Find out which one you have, in two minutes of WP-CLI
You do not need a working wp-admin to diagnose any of this. WP-CLI runs outside the admin menu, so it is not blocked by the check that is blocking you.
Start with the prefix and what is actually in the database:
wp db prefix
wp db query "SELECT option_name FROM $(wp db prefix)options WHERE option_name LIKE '%user_roles'"
wp db query "SELECT user_id, meta_key FROM $(wp db prefix)usermeta WHERE meta_key LIKE '%capabilities'"
If wp db prefix prints abc_ and the queries return wp_user_roles and wp_capabilities, you have the prefix mismatch. If the option exists under the right name, look at the roles and at your own user:
wp role list
wp user get 1 --field=roles
wp user list-caps 1
An empty roles field with a working wp role list means your user lost its role. An administrator role that exists but is missing capabilities like manage_options or activate_plugins means something edited the role.
To test the exact capability a screen needs, ask WordPress directly as that user:
wp eval 'var_dump( current_user_can( "activate_plugins" ) );' --user=1
For the ?page= case, list what is inactive and compare the slug in the URL:
wp plugin list --status=inactive
Log the check that failed
When the cause is not obvious, make WordPress tell you. Core fires admin_page_access_denied immediately before the wp_die() in menu.php, so a small must-use plugin can record what was denied and to whom:
<?php
// wp-content/mu-plugins/log-access-denied.php
add_action( 'admin_page_access_denied', function () {
global $pagenow, $plugin_page;
$user = wp_get_current_user();
error_log( sprintf(
'Access denied: pagenow=%s plugin_page=%s parent=%s user=%d roles=%s',
$pagenow,
$plugin_page ?? '-',
get_admin_page_parent(),
$user->ID,
implode( ',', $user->roles ) ?: 'none'
) );
} );
A line with plugin_page set is the unregistered-page case, and a line with roles=none is the missing-role case.
Anything else is a capability your role does not have for that parent menu.
The hook only covers the menu check. The Network Admin screens call wp_die() directly, so a denial there will not be logged by this plugin.
The log line needs WP_DEBUG_LOG switched on. On a SandyWP sandbox, Debug mode toggles it and shows debug.log next to the switches, so you do not have to edit wp-config.php.
Fix each cause
Unregistered plugin page. Reactivate the plugin with wp plugin activate <slug>, or remove the stale link. There is nothing to repair.
Prefix mismatch. Either set $table_prefix back to the prefix the tables actually use (wp db tables shows it), or rename the keys to match the new prefix:
UPDATE abc_options SET option_name = 'abc_user_roles' WHERE option_name = 'wp_user_roles';
UPDATE abc_usermeta SET meta_key = CONCAT('abc_', SUBSTRING(meta_key, 4)) WHERE meta_key LIKE 'wp\_%';
The second query also renames plugin meta keys that start with wp_, which is usually what you want after a prefix change but is worth checking first. The table prefix post lists the other keys that carry the prefix.
Lost role. wp user set-role 1 administrator assigns it again.
Edited role. wp role reset administrator restores the default capabilities of a core role. It does not know about capabilities a plugin added, so re-run that plugin's setup or re-grant them with wp cap add.
Damaged user_roles. Restore the option from a backup, or from the source site if this happened during a migration. Rebuilding it by hand means rebuilding every plugin's custom roles too.
Make the fix on a copy first
Every fix above is a write to wp_options or wp_usermeta, the two tables that decide who can log in. Getting the serialized user_roles value wrong locks out every user at once, including the person fixing it.
That makes this a job for a copy. Bring the site into a sandbox with the Cloner plugin, which only reads your live database and files to build the archive and modifies nothing on the live site.
The copy carries the same prefix, the same roles and the same plugins, so it shows the same error. Then run the diagnosis over SSH with WP-CLI, which is preinstalled, try the fix, and confirm that the Dashboard, Plugins and the plugin pages you need all load for the right user.
When it works, you have the exact commands to run on the live site, in the order that worked.
When a sandbox is the wrong tool
If you are an Editor or an Author and the screen belongs to administrators, nothing is broken. Ask whoever runs the site, because the fix is a role change only they should make.
If the error appeared on a live site you have not changed, and your administrator account has lost its role without anyone touching it, treat it as a possible compromise before treating it as a bug. Check wp user list --role=administrator for accounts you do not recognise and involve whoever handles security for the site.
A copy proves the fix, but it does not apply it. You still run the same commands on production, with a fresh backup, in a quiet window.
