Didn’t get the WordPress recovery mode email?

Your site says “There has been a critical error on this website. Please check your site admin email inbox for instructions.” The inbox has nothing from WordPress. That line is shown whenever the crash happens on the dashboard or the login page; it does not mean an email went out this time. WordPress sends the recovery email at most once every 24 hours, to one address, through the same mail setup as every other message the site sends. If the first one went to an inbox nobody reads, or the crash took the mail setup down with it, there is no second email coming. You can get back in without it.

What WordPress does when it shows that message

When a plugin or theme throws a fatal PHP error, a shutdown handler in core catches it (WP_Fatal_Error_Handler, as of WordPress 7.1.3). It works out which plugin or theme folder the failing file lives in and hands the error to the recovery mode service. That service sends the email only when all of these hold:

  • The site is not multisite. Core never starts recovery mode on multisite, so no email is sent and the page shows only the generic “There has been a critical error on this website.”
  • The fatal error handler is on. define( 'WP_DISABLE_FATAL_ERROR_HANDLER', true ); in wp-config.php turns the whole mechanism off.
  • The request was the dashboard, the login page, or one of a few admin Ajax actions. Core calls these protected endpoints. A visitor who hits the crash on the front end sees the generic message, and nothing is sent. The email goes out only if the same error also fires when someone loads /wp-admin/ or wp-login.php; a plugin that crashes only on front-end pages never triggers one.
  • The error came from a plugin or theme. The file has to sit under the plugins directory or a theme directory. A fatal in core or in a must-use plugin produces no email, even when the inbox line appears.
  • The request isn’t part of a recovery session. When the fatal hits a browser already logged in through a recovery link, core pauses the offending plugin or theme for that session instead of sending another email.
  • No email went out in the last 24 hours. The default window is DAY_IN_SECONDS, adjustable with the recovery_mode_email_rate_limit filter.

If you saw the “check your inbox” line, the first three already hold: that line only appears on a protected endpoint of a single site with recovery mode running. A fatal in wp-config.php, or in a must-use plugin while it is loading, happens before recovery mode starts, so it never shows the line. What is left open is whether the error came from a regular plugin or theme, whether an email went out recently, and where it went.

The recipient is the RECOVERY_MODE_EMAIL constant if it is defined and holds a valid address, otherwise the Administration Email from Settings → General. The message goes out through wp_mail() with the subject “[Site name] Your Site is Experiencing a Technical Issue”. The login link in it stays valid for 24 hours by default (the recovery_mode_email_link_ttl filter; core never sets it shorter than the rate limit).

Core writes the send time to the recovery_mode_email_last_sent option before it calls wp_mail(), so a send that fails still uses up the 24-hour window.

Why it didn’t arrive

Four causes, in the order worth checking them. If the site’s own WP-CLI commands crash, add --skip-plugins --skip-themes, as below; must-use plugins still load.

It was sent hours ago. The first dashboard load after the crash sent it, perhaps to someone else on the team, perhaps during the night. Every later visit to the dashboard repeats the inbox line without sending anything. Check when it went out:

wp option get recovery_mode_email_last_sent --skip-plugins --skip-themes

That returns a Unix timestamp (date -d @<timestamp> converts it; date -r <timestamp> on macOS). If it says Could not get 'recovery_mode_email_last_sent' option. Does it exist?, core has not sent one since the option was last cleared. Leaving recovery mode clears it.

It went to an inbox nobody reads. The Administration Email is often the developer who built the site, an address on a domain that has since lapsed, or a shared mailbox with no owner. Check both places core looks:

wp option get admin_email --skip-plugins --skip-themes
wp config get RECOVERY_MODE_EMAIL --skip-plugins --skip-themes

If the address is dead, changing it the normal way needs a confirmation email too. Changing the admin email when the old inbox is unreachable covers the WP-CLI and database routes.

The crash took out the mail setup. If the crash happened while WordPress was still loading plugins (the usual shape after a bad update), your SMTP plugin may never have taken over. The recovery email then went out the way an unconfigured WordPress sends mail: PHP mail(), from wordpress@yourdomain, with no SMTP login. Hosts that block mail() drop it outright. Where it does leave the server, it isn’t sent through your mail provider, and WordPress adds no DKIM signature of its own; unless the host’s mail server signs for your domain, it arrives unauthenticated, which usually lands it in spam.

Whether that happens depends on the mailer. WP Mail SMTP and Easy WP SMTP install their mailer on the plugins_loaded action, which fires only after every active plugin has loaded, so a fatal during loading leaves them out of the picture. FluentSMTP and Post SMTP (in its default mode) replace wp_mail() as soon as their own file loads. They are in place only if their folder name sorts before the crashing plugin’s, because WordPress loads active plugins in alphabetical order by folder. FluentSMTP’s replacement reads its saved connection settings directly, so it probably still sends through your provider when plugins_loaded never fires; that is a reading of the source, not something we have tested.

If the mailer itself crashes while loading, the same applies. If it crashes later, while sending, its code is already in place and the recovery email goes through the same broken mailer, so it probably fails too. A fatal that happens while the dashboard is rendering leaves a healthy mailer fully loaded, and the email goes out the normal way.

To confirm this cause, look in the mailer’s email log for “Your Site is Experiencing a Technical Issue”. FluentSMTP logs by default and keeps 14 days; WP Mail SMTP’s log is a Pro feature you have to switch on. If logging was on and there is no entry, the message went around the mailer. Then check the spam folder, and the host’s mail log if you have one.

The site’s mail never worked. No mailer plugin, and a host that blocks or discards mail(). Password resets and form notifications have been vanishing too; the crash is just when it became urgent. Troubleshooting WordPress email works through that, and how WordPress sends email explains the default path.

Once the recipient or the mail path is fixed, and while the plugin is still crashing, you can trigger a fresh email: run wp option delete recovery_mode_email_last_sent --skip-plugins --skip-themes, then load /wp-admin/. The fatal fires again and core sends a new link.

Getting in without the email

To get in, you need the name of the plugin or theme that crashed, and the file path in the error gives it: the folder name after wp-content/plugins/ for a plugin, or after wp-content/themes/ for a theme.

  • Find the error in wp-content/debug.log (if WP_DEBUG and WP_DEBUG_LOG are both on; a path in WP_DEBUG_LOG moves the file) or in your host’s PHP error log.
  • Deactivate the plugin with wp plugin deactivate <folder> --skip-plugins --skip-themes, or rename its folder over SFTP or the host’s file manager. WordPress skips a plugin whose folder is missing and deactivates it the next time the Plugins screen loads. For a theme, switch away from it with wp theme activate <another-theme> --skip-themes.

Recovering a site after a Contact Form 7 update crashed it walks through one real incident end to end.

Before the next crash

  • Add define( 'RECOVERY_MODE_EMAIL', '[email protected]' ); to wp-config.php, pointing at an inbox someone checks, on a domain other than the site’s own. If the site’s domain is the thing that broke, its mailboxes break with it.
  • Route WordPress mail through an authenticated mailer plugin and an SMTP provider, so day-to-day mail does not depend on PHP mail().
  • Send a test message and confirm it lands in the inbox, not spam. A test from a healthy site proves the normal path; it says nothing about the plugins-still-loading case above, which is why the off-domain recipient matters.

The catalogue of every email WordPress core sends lists the recovery email alongside the rest, with its filters. If you are pruning core’s notifications, disabling WordPress’s automatic emails explains why this is one to leave on.