Skip to content

WordPress maintenance

WordPress “Sorry, you are not allowed to access this page” after a migration: the table prefix

In short

"Sorry, you are not allowed to access this page" after a migration usually means WordPress cannot find your capabilities. It looks them up under your table prefix, so if the prefix changed but the usermeta and options rows still carry the old one, an admin has no rights. Update those rows to the new prefix.

Key points

  • WordPress reads an admin's rights from a usermeta row named after the table prefix, such as wp_capabilities. If no row matches, the user has no capabilities.
  • The role definitions live in an options row named the same way, such as wp_user_roles.
  • You can still log in, because the password check does not use the prefix. Only the rights check fails.
  • Back up the database first. The fix is two SQL updates, one on the usermeta table and one on the options table.
On this page (10)
  1. Why does WordPress say you are not allowed to access this page?
  2. How does the table prefix decide who is an admin?
  3. Why can you log in but still get the message?
  4. What changes the prefix during a migration?
  5. How do you fix it?
  6. Why does step 4 need the WHERE clause?
  7. What else can cause this message?
  8. What did we not test?
  9. Is your dashboard still closed to you?
  10. Questions and answers

Why does WordPress say you are not allowed to access this page?

The message comes from WordPress, not from your host. Before it shows an admin screen, WordPress asks whether your user may see it. If the answer is no, wp-admin/includes/menu.php stops with “Sorry, you are not allowed to access this page.” and a 403 status.

After a migration, the answer is usually wrong. Your rights are still in the database, under a name WordPress no longer looks for.

If you were mid-move when this appeared, our WordPress care and fixes page covers how we handle migrations and the cleanup after them.

How does the table prefix decide who is an admin?

Every table name starts with a prefix, wp_ by default, set by $table_prefix in wp-config.php. WordPress also puts it inside two row names.

In the usermeta table, each user has a row such as wp_capabilities that holds their role. A function called get_caps_data() reads it. If the value is not an array, it returns an empty list, and an empty list means no rights.

In the options table, a row such as wp_user_roles says what each role may do. class-wp-roles.php builds that name from the current prefix.

Change the prefix and WordPress looks for the new names. The rows keep their old ones.

Why can you log in but still get the message?

Logging in checks a password, which has nothing to do with the prefix. The rights check comes after, on the first admin screen.

On our test site the login was accepted, and WordPress sent us to the home page instead of the dashboard. Typing /wp-admin/ gave the message with a 403, and so did the profile screen.

What changes the prefix during a migration?

A move tool or a host restore can import the tables under a different prefix. A security plugin can rename it as a hardening step, sometimes without touching the rows. Or someone edits $table_prefix to match a staging copy.

The WordPress handbook is plain about it: if you change the table prefix, you must also update the usermeta entries.

How do you fix it?

Back up the database first. SQL changes are permanent.

  1. Note the value of $table_prefix in wp-config.php. That is the new prefix.
  2. In phpMyAdmin or your host’s database tool, search meta_key in the usermeta table for “capabilities”. A different prefix on that key is the mismatch.
  3. Search option_name in the options table for “user_roles”. Same check.

Step 4 renames every usermeta key that starts with the old prefix. Use your real prefixes, and keep the backslash: in LIKE, a bare underscore matches any character.

UPDATE `newprefix_usermeta` SET `meta_key` = REPLACE( `meta_key` , 'oldprefix_', 'newprefix_' ) WHERE `meta_key` LIKE 'oldprefix\_%';

Step 5 renames the roles row. This statement is ours, built from the key name in class-wp-roles.php.

UPDATE `newprefix_options` SET `option_name` = REPLACE( `option_name` , 'oldprefix_user_roles', 'newprefix_user_roles' );

Step 6: log in again and open /wp-admin/. On our MariaDB 11.8 test site, step 4 renamed three keys: wp_capabilities, wp_user_level and wp_dashboard_quick_press_last_post_id. Step 5 renamed wp_user_roles. The next login went straight to the dashboard, and nothing else needed changing.

Why does step 4 need the WHERE clause?

The handbook gives step 4 without it, so the replace hits every key that contains the old prefix anywhere. On our first test run, on SQLite, that version also turned dismissed_wp_pointers into dismissed_dc_pointers, a fixed key name it should have left alone.

With the WHERE clause, MariaDB left dismissed_wp_pointers as it was. It also left a test key we added, wpxlab_probe, which a LIKE without the backslash would have caught. Running the statement a second time matched 0 rows.

REPLACE still changes every copy of the old prefix inside a key it picks. So read the rows first: SELECT meta_key FROM newprefix_usermeta WHERE meta_key LIKE 'oldprefix\_%';

What else can cause this message?

A plugin that edits roles can remove a capability. The message then shows on one screen, so look at which plugin owns it.

A missing user_roles row closes the whole dashboard. We deleted that row on our test site and got the same 403, though usermeta still said administrator: no role list said what an administrator may do. Visiting the dashboard did not create the row again.

If the site is also down for visitors, see Error establishing a database connection in WordPress. If the problem started after you changed the site address, the site address lockout is the closer match.

What did we not test?

We ran these checks on WordPress 7.1.3 on 14 Oct 2026, on two test sites. The first ran on SQLite through the SQLite Database Integration plugin, which could not rename tables, so we copied them. The second ran on MariaDB 11.8.9, where steps 4 and 5 ran as written. The missing user_roles check ran on SQLite only.

These we did not test:

  • MySQL itself, and the row counts phpMyAdmin will report.
  • Multisite, where each site has its own prefix and role key.
  • Plugins that edit roles, and security plugins or host restores that rename the prefix for you.

Is your dashboard still closed to you?

If the prefix matches and the message stays, or the move left more than one thing broken, tell us what the site shows and we will look at the database with you.

Where did these facts come from?

Questions and answers

Why can I log in but not open the dashboard?

Logging in checks your password. Opening an admin screen checks your capabilities, and WordPress finds those under a key that starts with the table prefix. If the key holds the old prefix, the check finds nothing.

Is my content gone?

No. Posts, pages and settings sit in their own tables. Only two kinds of row carry the old prefix as part of their name, and they control who may do what.

Do I need to change the table prefix back instead?

You can, if the tables themselves still use the old prefix and only wp-config.php changed. The prefix in wp-config.php, the table names and the key names must all agree.

Still stuck? Send us the page address and what you see