It’s a familiar story for anyone managing WordPress sites: you log into the admin dashboard, expecting to update a plugin or tweak a post, and suddenly you’re stuck in an endless redirect loop. The browser keeps sending you to /wp-admin/upgrade.php, only to greet you with the infuriating message — “No Update Required.”
You refresh, it happens again. Clear your browser cache? No luck. The site works fine on the frontend, but the admin panel just won’t let you in.
This article walks through why it happens and how to fix it — cleanly, safely, and with a few WP-CLI commands that will make you look like a pro.
Why This Happens
At the heart of it, WordPress thinks your database version and core code version don’t match. That mismatch triggers an automatic redirect to the upgrade script, even when no upgrade is actually needed.
But that’s not the whole story. In most cases, the real cause is stale cache data. If you’re using Redis, Memcached, or another object cache, WordPress might be holding onto an outdated record that tells it the database needs an update — even when it doesn’t.
Common culprits
- Persistent object cache (Redis, Memcached, or APC/APCu) holding old schema info.
- Database version mismatch between the
wp_optionsvalue and the code’s$wp_db_version. - Lingering transients or updater locks.
- Plugin redirects interfering with the login flow.
- Incorrect site URLs in your configuration or database.
Step-by-Step: How to Fix the Loop
You don’t need to reinstall WordPress or restore backups. Follow these steps — in order — and you’ll have it sorted in minutes.
1) Clear the caches
If you have WP-CLI:
|
1 2 |
wp cache flush |
If Redis or Memcached is enabled, restart or flush those services too. You can also temporarily disable object caching:
|
1 2 |
mv wp-content/object-cache.php wp-content/object-cache.php.bak |
2) Verify your core files
Make sure your WordPress files are intact:
|
1 2 |
wp core verify-checksums |
If mismatches appear, reinstall core safely (your content stays untouched):
|
1 2 |
wp core download --force |
3) Compare the database version
WordPress stores its database schema version in two places: one in the code, one in the database.
Check the code’s version:
|
1 2 |
wp eval 'global $wp_db_version; echo $wp_db_version . PHP_EOL;' |
Check the database’s version:
|
1 2 |
wp option get db_version |
If they don’t match, align them:
|
1 2 3 |
wp option update db_version <VALUE_FROM_wp_db_version> wp cache flush |
4) Clean up upgrade locks
Sometimes leftover transients or locks trick WordPress into thinking an upgrade is pending.
|
1 2 3 |
wp transient delete --all wp option delete core_updater.lock |
5) Disable all plugins (just temporarily)
A plugin might be redirecting you.
|
1 2 |
mv wp-content/plugins wp-content/plugins.off |
Try logging in again. If it works, restore the folder and re-enable plugins one at a time.
6) Double-check your URLs
Ensure the site URLs are correct both in wp-config.php and the database:
|
1 2 3 |
wp option get home wp option get siteurl |
Fix mismatches or typos as needed.
7) Remove the .maintenance file (if it exists)
|
1 2 |
rm -f .maintenance |
8) Restart PHP or your web server
This clears any stale opcode cache (like OPcache or APCu) that might still be referencing old code.
Mini Decision Tree
- Loop + Redis/Memcached active? → Flush Redis/Memcached, disable
object-cache.php, then retry. wp core verify-checksumsfails? → Runwp core download --forceand test again.db_version≠$wp_db_version? →wp option update db_version <VALUE_FROM_wp_DB>and flush caches.- Still looping after above? → Temporarily disable plugins, clear transients/locks, confirm URLs, restart PHP-FPM/Apache.
Operational Safety (Production)
- Snapshot first: Take a quick DB snapshot/backup before step 3 on production.
- Cautious cache flushing: In shared cache environments, prefer targeted key flushes over global
FLUSHALL. - No content risk:
wp core download --forcedoes not touchwp-contentor your database.
Cache Service Commands (Handy References)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
# Redis (beware on shared instances) redis-cli FLUSHALL # Memcached (local default port) echo 'flush_all' | nc 127.0.0.1 11211 # PHP-FPM restart (Ubuntu/Debian) sudo systemctl restart php*-fpm # Apache or Nginx (Ubuntu/Debian) sudo systemctl restart apache2 sudo systemctl restart nginx |
Tip: If you’re using a managed Redis/Memcached cluster, use its dashboard or a namespace-specific flush instead of global commands.
A Quick One-Liner (for Advanced Users)
If you just want to reset everything in one go:
|
1 2 3 4 5 6 7 |
wp cache flush \ && wp core verify-checksums || wp core download --force \ && DBV_CODE=$(wp eval 'global $wp_db_version; echo $wp_db_version;') \ && DBV_DB=$(wp option get db_version) \ && [ "$DBV_CODE" != "$DBV_DB" ] && wp option update db_version "$DBV_CODE" || true \ && wp transient delete --all |
For Multisite Users
If you’re running a multisite network, repeat the version check for each site:
|
1 2 3 |
wp site list --fields=url wp site list --field=blog_id | xargs -I % wp --url=$(wp site get % --field=url) option get db_version |
Every site should report the same db_version as the main WordPress install.
Wrapping Up
This issue is frustrating, but it’s rarely catastrophic. The problem almost always comes down to a cache mismatch or a stale database value. Clearing caches and aligning versions usually resolves the redirect immediately.
If you manage multiple WordPress installations, adding a quick health check in your monitoring stack — one that tests /wp-admin responses — can help you catch this before clients do.




