Skip to content

How to fix "Maximum execution time exceeded" in WordPress

PHP stopped a request because it ran longer than the server allows, which is 30 seconds by default. The log names the file that was running when time ran out. Raise the limit for a one-off long job. If an ordinary page needs longer, find what is slow instead.

By
WP Ministry
Published
Tested on
WordPress 7.1.3, PHP 8.3.35

In short

  • The limit is a safety setting. One request ran past it, and PHP stopped that request.
  • The debug log names the file PHP was running when time ran out. Start there.
  • Raising the limit is right for a one-off long job, such as an import. For an ordinary page it hides the problem.
  • Where the limit can be raised depends on how PHP runs on your server. It is .htaccess, .user.ini or the host's own settings.

PHP, the language WordPress is written in, gives each request a fixed time to finish: 30 seconds unless the server is set otherwise. When a request runs past it, PHP stops the request and reports "Maximum execution time of 30 seconds exceeded". The number in the message is the limit in force. WordPress then shows visitors "There has been a critical error on this website" in its place, and the real message is in the error log.

The error itself deletes nothing. What was running did not finish, though: an import that was cut off has brought in only part of its data. If an update was cut off and the site now says it is unavailable for maintenance, Briefly unavailable for scheduled maintenance covers bringing it back.

Work out which case you have

  • It happened during one long job you started, such as an import, a backup or an update, and the rest of the site works. The job needs more time. Go to the third fix.
  • It happens on ordinary pages, or on every page. Something is stuck or slow. More time would only make the wait longer, so start with the first fix.

Where it goes wrong

A page request passes through each of these in turn. This one comes from PHP, the language WordPress runs on.

  1. Browser
  2. DNS
  3. HTTPS
  4. CDN or firewall
  5. Web server
  6. PHP (this error comes from here)
  7. WordPress
  8. Database and files

What causes it

How to fix it

Find what was running when time ran out

  • Takes care
  • Low risk
  • About 15 minutes
  • Steps tested on WordPress 7.1.3

The full message ends with a file and a line number: where PHP was at the moment it was stopped. WordPress hides that from visitors, but will write it to a log if you ask.

  1. Step 1: Turn the debug log on

    In wp-config.php, find the line define( 'WP_DEBUG', false ); and replace it with these three. If you have WP-CLI, the commands below do the same.

    wp-config.php
    define( 'WP_DEBUG', true );
    define( 'WP_DEBUG_LOG', true );
    define( 'WP_DEBUG_DISPLAY', false );
  2. Step 2: Do again what failed

    Load the page, or start the job, and wait for the error. Once is enough.

  3. Step 3: Read the log

    Open wp-content/debug.log and find the newest line with "Maximum execution time". It looks like this:

    The WordPress error message and debug.log decoder reads pasted lines in your browser and shows what each one means and which plugin or theme it points at. Nothing is sent.

    text
    PHP Fatal error:  Maximum execution time of 30 seconds exceeded in /home/example/public_html/wp-content/plugins/plugin-folder-name/sync.php on line 212
  4. Step 4: Act on the path

    • Through wp-content/plugins/ and a folder name: PHP was inside that plugin. Use the next fix.
    • Through wp-content/themes/: PHP was inside the theme. The white screen of death has the steps for switching to another theme.
    • Through wp-includes/ or wp-admin/: a file of WordPress's own was running, on behalf of whatever called it. The line does not say what that was. How to find and fix a WordPress plugin conflict shows how to narrow it down by switching plugins off in halves.
  5. Step 5: Turn the debug log off again

    Put the line back to define( 'WP_DEBUG', false );. WordPress's own advice is not to leave debugging on a live site, so delete debug.log when you have read it.

With WP-CLI, turn the log on:

bash
wp config set WP_DEBUG true --raw
wp config set WP_DEBUG_LOG true --raw
wp config set WP_DEBUG_DISPLAY false --raw

And off again when you have what you need:

bash
wp config set WP_DEBUG false --raw
wp config set WP_DEBUG_LOG false --raw

Switch off the plugin the log names

  • Takes care
  • Low risk
  • About 10 minutes
  • Steps tested on WordPress 7.1.3
  1. Step 1: Switch the plugin off

    If the dashboard loads, open Plugins and choose Deactivate under the plugin's name. If it does not, use your host's file manager or SFTP: open wp-content/plugins/ and rename the plugin's folder, for example by adding -off to its name. WordPress can no longer find the plugin and switches it off.

    With WP-CLI, use the folder's name. The two extra options run the command without loading any plugin or theme, the slow one included:

    bash
    wp plugin deactivate plugin-folder-name --skip-plugins --skip-themes
  2. Step 2: Do again what failed

    If it now finishes, that plugin was using the time.

  3. Step 3: Decide what to do about the plugin

    Update it if an update is waiting, or replace it, and tell its author what the log said. If the plugin's job is to talk to another service, the delay may be on that side, and its author is the one to ask.

If the log names no plugin, or switching one off changes nothing, How to find and fix a WordPress plugin conflict covers switching every plugin off and bringing them back in halves.

To undo it: Rename the folder back, or activate the plugin again.

Raise the limit in .htaccess

  • Easy
  • Back up first
  • About 5 minutes
  • Steps tested on WordPress 7.1.3

This is the right fix when one long job needs the time. It works only where PHP runs as an Apache module.

  1. Step 1: See how PHP runs on your server

    In the dashboard, open Tools, then Site Health, then the Info tab, and open the Server section. If "PHP SAPI" says apache2handler, PHP runs as an Apache module and this fix applies. If it says fpm-fcgi or cgi-fcgi, use the next fix. "PHP time limit" on the same screen is the limit now in force.

  2. Step 2: Add this line at the end of .htaccess

    The file is in the site's main folder, beside wp-config.php. Put the line on a line of its own, below # END WordPress.

    .htaccess
    php_value max_execution_time 300
  3. Step 3: Run the job again

    "PHP time limit" in Site Health should now say 300, which is five minutes. Start the import, backup or update again.

  4. Step 4: Take the line out when the job is done

    The limit is there so that a stuck page cannot tie up the server. With the line left in, a stuck page holds on for five minutes instead of 30 seconds.

If "PHP time limit" still shows the old number, the host has set the limit in a way .htaccess cannot override. Go to the last fix.

If an ordinary page, not a long job, is what runs out of time, do not stop here. A higher limit lets a slow page finish, but every visitor still waits for it. Find what is slow with the first fix.

To undo it: Remove the line from .htaccess.

Raise the limit in .user.ini

  • Easy
  • Low risk
  • About 10 minutes

Where PHP runs as CGI or FastCGI, which includes PHP-FPM, it reads per-folder settings from a file named .user.ini, not from .htaccess.

  1. Step 1: Open or create .user.ini in the site's main folder

    It sits beside wp-config.php. Its name begins with a dot, so turn on "Show hidden files" in your file manager. If the file is already there, keep what it holds.

  2. Step 2: Add this line

    .user.ini
    max_execution_time = 300
  3. Step 3: Wait five minutes, then check

    PHP reads these files again only every 300 seconds by default, so the change is not immediate. Then open Tools, then Site Health, then the Info tab: "PHP time limit" in the Server section should say 300. If it still shows the old number, PHP on your server is not reading the file. Go to the next fix.

  4. Step 4: Run the job again, and take the line out afterwards

    As with .htaccess, a one-off job needs the time once.

To undo it: Remove the line, or delete the file if you created it.

Change it in the host's PHP settings, or ask the host

  • Easy
  • No risk
  • About 15 minutes

A host can set the limit so that .htaccess cannot change it, and can switch .user.ini files off. Then the setting is theirs to change.

  1. Step 1: Look for a PHP settings page in your hosting panel

    Many hosts let you change max_execution_time yourself, under a name such as "PHP settings" or "PHP options".

  2. Step 2: If there is none, ask support

    Send them the full line from the log and say what was running. Ask them to raise max_execution_time for your site, and whether your plan allows it. Ask too whether the web server has a timeout of its own: a longer limit in PHP does not lift that one.

When to get help

If the limit is already at 300 seconds and a page still runs out of time, or the log names only WordPress's own files and switching plugins off has not found the cause, more time will not fix it. Something is doing work it should not on every request, and finding it means measuring the page on a copy of the site.

Common questions

What number should I set?

For a one-off job, 300. It is the figure WordPress itself asks for when it installs an update. PHP's manual also notes that the web server can have a timeout of its own. Apache's is its Timeout setting, which is 60 seconds unless the server's configuration gives another figure, so a higher number may change nothing. Setting 0 removes the limit altogether. Do not do that on a live site: the limit is what stops a stuck page from tying up the server.

Does time spent waiting on the database or another server count?

On Windows it does. On other systems, by default, it does not: PHP's manual says time spent on system calls, stream operations and database queries is left out, and only the processor time the script itself uses is counted. Builds of PHP that measure elapsed time count the waiting too. Either way, the file the log names is where PHP was when time ran out.

Why does it happen only sometimes?

Different requests do different amounts of work. Showing a post is a small job. An import, a backup or an update can be a large one. A job run from the command line with WP-CLI is not held to the same limit: PHP's default there is 0, which means none.

More on this subject

Would you rather we fixed it?

Quick Fix is $49. One issue, one site, up to about an hour. No fix, no fee. 30-day warranty. It starts with a free diagnosis.