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.
- Browser
- DNS
- HTTPS
- CDN or firewall
- Web server
- PHP (this error comes from here)
- WordPress
- Database and files
What causes it
One long job needs more time than the limit allows
CommonAn import, a backup or a large update can be long by nature. WordPress itself asks PHP for 300 seconds when it installs an update.
Fix: Raise the limit in .htaccess, or Raise the limit in .user.ini
A plugin or theme is stuck, or does far too much on every page
CommonCode that loops without end, or repeats heavy work on each request, uses up any limit. Stopping it is what the limit is for.
Fix: Find what was running when time ran out, or Switch off the plugin the log names
The page waits on a slow outside service
SometimesOn Windows, and on builds of PHP that measure elapsed time, time spent waiting on another server counts toward the limit. By default on other systems it does not, and only the script's own processor time is counted.
Fix: Find what was running when time ran out, or Switch off the plugin the log names
The host sets a low limit
SometimesPHP's default is 30 seconds, and a host can set a different figure. A low one can stop work that is not at fault.
Fix: Raise the limit in .htaccess, or Raise the limit in .user.ini, or Change it in the host's PHP settings, or ask the host
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.
Step 1: Turn the debug log on
In
wp-config.php, find the linedefine( 'WP_DEBUG', false );and replace it with these three. If you have WP-CLI, the commands below do the same.wp-config.phpdefine( 'WP_DEBUG', true ); define( 'WP_DEBUG_LOG', true ); define( 'WP_DEBUG_DISPLAY', false );Step 2: Do again what failed
Load the page, or start the job, and wait for the error. Once is enough.
Step 3: Read the log
Open
wp-content/debug.logand 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.
textPHP Fatal error: Maximum execution time of 30 seconds exceeded in /home/example/public_html/wp-content/plugins/plugin-folder-name/sync.php on line 212Step 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/orwp-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.
- Through
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 deletedebug.logwhen you have read it.
With WP-CLI, turn the log on:
wp config set WP_DEBUG true --raw
wp config set WP_DEBUG_LOG true --raw
wp config set WP_DEBUG_DISPLAY false --rawAnd off again when you have what you need:
wp config set WP_DEBUG false --raw
wp config set WP_DEBUG_LOG false --rawSwitch off the plugin the log names
- Takes care
- Low risk
- About 10 minutes
- Steps tested on WordPress 7.1.3
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-offto 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:
bashwp plugin deactivate plugin-folder-name --skip-plugins --skip-themesStep 2: Do again what failed
If it now finishes, that plugin was using the time.
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.
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 saysfpm-fcgiorcgi-fcgi, use the next fix. "PHP time limit" on the same screen is the limit now in force.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..htaccessphp_value max_execution_time 300Step 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.
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.
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.Step 2: Add this line
.user.inimax_execution_time = 300Step 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.
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.
Step 1: Look for a PHP settings page in your hosting panel
Many hosts let you change
max_execution_timeyourself, under a name such as "PHP settings" or "PHP options".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_timefor 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.
- GuideLocked out of WordPress admin: find which lockout you have and get back in
- GuideSlow WordPress admin: how to find the cause and fix it
- ResourceWooCommerce checkout is down: a runbook
- GuideWordPress site not showing up on Google: what to check, in order
- Guideadmin-ajax.php high CPU usage in WordPress: how to find what is calling it
- GuideHow to change WordPress permalinks without breaking your old links

