WordPress Stuck in Maintenance Mode: What the Core Code Checks
On this page, 8 sections
WordPress is stuck in maintenance mode when a file called .maintenance is sitting in the site’s root folder with a recent timestamp, usually left behind by an update that did not finish.
Delete that file over SFTP or SSH and the site comes back. The file is hidden because its name starts with a dot, so many FTP clients do not list it until you turn on hidden files.
Core also gives up on the file by itself. In the code I read on 11 October 2026, WordPress treats the file as stale once the timestamp inside it is 10 minutes old. If your site is still showing the message after that, something other than a simple stale file is going on, and there are four likely ones below.
What WordPress actually checks
The check lives in wp_is_maintenance_mode() in wp-includes/load.php. I read it from the WordPress development repository on 11 October 2026. In order, it does this:
- If there is no
.maintenancefile in the folder that holdswp-load.php(the constantABSPATH), or WordPress is mid-install, maintenance mode is off. - Otherwise it includes the file. The file sets one variable,
$upgrading, to a Unix timestamp. - If the current time minus
$upgradingis 600 seconds or more, maintenance mode is off. - It then lets a special scraping request through (used when core is checking for fatal errors).
- It applies a filter named
enable_maintenance_mode. Code that loads before plugins can return false there, and then maintenance mode is off. - If none of that turned it off, the visitor gets the message.
The message comes from wp_maintenance() in the same file. It sends a Retry-After: 600 header, and calls wp_die() with the text “Briefly unavailable for scheduled maintenance. Check back in a minute.” and a 503 status. If a file named maintenance.php exists in wp-content, core loads that instead and stops.
The file is created by WP_Upgrader::maintenance_mode() in wp-admin/includes/class-wp-upgrader.php. Before an update it writes the string <?php $upgrading = <current time>; ?> into .maintenance. When the update finishes it deletes the file. If PHP is killed in between, nothing deletes it.
Four reasons it is still stuck after 10 minutes
1. The update is still being retried
If an update keeps failing and keeps being retried, each run writes a fresh timestamp, which resets the 10-minute window. I have not captured this on a site; it follows from the way the file is written.
The site looks permanently stuck, but the file’s timestamp is new every time. Open the file, read the number, and compare it to the current Unix time. If it is recent, something is writing it.
Check whether auto-updates are queued. In the dashboard, the Updates screen shows what is pending. A host-level task or a management tool that runs updates on a schedule can also be doing it.
2. The timestamp is in the future
The test in the code is the current time minus $upgrading, compared against 600. If $upgrading is a time later than now, that subtraction is negative and the test never passes. I derived this from reading the code. I did not create such a file on a test site.
A file edited by hand or a server clock that was wrong when the file was written could produce a future value. This is an edge case, and I would check it last. The fix is the same: delete the file.
3. It is not the core file at all
Many sites use a plugin or a host feature that shows its own “maintenance” or “coming soon” page. That is separate from the core mechanism and it ignores the 10-minute rule. If there is no .maintenance file in the root, look at your plugin list. Disable the maintenance, coming-soon or under-construction plugin by renaming its folder in wp-content/plugins.
Also check for wp-content/maintenance.php. Core loads this file whenever maintenance mode is active, but a plugin or a custom setup can also place a drop-in there. Its content is what visitors see, so the text you are looking at may not be the default message.
4. A cache is serving the old page
The core page is sent with a 503 status. A host or CDN layer, or a page cache that stored the response, can keep showing the message after the file is gone. Purge the page cache and the CDN cache, then load the site in a private window. My article on which WordPress caching layer is failing covers how to tell which layer is serving what.
The fix, step by step
- Connect over SFTP or SSH to the folder that holds
wp-load.php. - Show hidden files. In an SSH session, run
ls -laand look for.maintenance. - Open it, and note the number after
$upgrading =. That is the time the update started. - Delete the file.
- Load the site. If the page is back, go to Dashboard, then Updates, and check what the interrupted update left behind.
With WP-CLI installed, the command is:
wp maintenance-mode status
wp maintenance-mode deactivate
The WP-CLI page lists activate, deactivate, status and is-active. I read the command reference on 11 October 2026 but did not run it on a live site. If the file is owned by a different user than the one running the command, the deletion can fail with a permissions error. File ownership on WordPress sites explains why ownership matters more than the numeric mode.
Finish the update that was interrupted
Deleting the file turns the site back on but does not repair a half-finished update. After the site loads, go to the Updates screen and run the update again for whatever was interrupted. If it fails again with the same symptom, the cause is in the server (PHP execution time, memory, disk space or file permissions), not in WordPress.
If the dashboard itself shows a blank page after the fix, that is a different fault with its own procedure, which I wrote up as the WordPress white screen and debug log.
A detail about fatal errors during an update
The fatal error handler in core has a check at the top of its handle() method: if maintenance mode is active, it returns without doing anything. The comment says it avoids triggering while updates are installed.
That is sensible, but going by that code it means a crash during an update skips the fatal error handler, so I would not expect a recovery mode email for it. I did not test this. If an update dies halfway, the first sign you get is the maintenance message. Plan on checking the server’s PHP error log when this happens.
When it is not maintenance mode
If the page you see is not the maintenance text, check the status code before you do anything else. A 503 with the maintenance text is this article. A 301 or 302 that sends the browser to another address is a redirect problem, and fixing 301 errors in WordPress is the place to start. A white page with no text is the debug log procedure.
Questions people ask
How long does WordPress stay in maintenance mode?
The core check treats the file as expired after 10 minutes. How long an update takes depends on your server.
Is it safe to delete the .maintenance file?
The file contains one timestamp and no site data. Core creates it before each update and removes it afterwards. The risk is not the file. It is the half-finished update behind it, so rerun the update after deleting it.
Why can I not see the .maintenance file?
Its name begins with a dot, so file managers and FTP clients hide it by default. Turn on “show hidden files”, or list the folder over SSH with ls -la.
Do this today
Connect over SFTP or SSH, show hidden files in the WordPress root, and check whether .maintenance is there. If it is, read the timestamp, delete it, then rerun the interrupted update.
Resources
- wp-includes/load.php, wp_maintenance() and wp_is_maintenance_mode(), read 11 October 2026.
- wp-admin/includes/class-wp-upgrader.php, WP_Upgrader::maintenance_mode(), read 11 October 2026.
- wp-includes/class-wp-fatal-error-handler.php, read 11 October 2026.
- WP-CLI: wp maintenance-mode, read 11 October 2026.