PHP Fatal Error: Maximum Execution Time of 30 Seconds Exceeded
A PHP script ran past the max_execution_time cap, so the engine aborted it before it could finish.
What you see
Fatal error: Maximum execution time of 30 seconds exceeded in /home/user/public_html/wp-content/plugins/some-plugin/includes/class-importer.php on line 312
What’s actually happening
A request hangs for roughly 30 seconds, then dies with this error or a 500. Imports stop halfway, a backup leaves a partial archive, or the admin spins and never returns. The line in the message is wherever the timer happened to expire (often a loop, a database call, or wp_remote_get), which may not be the slow part itself. Note this counts script execution time, not always wall-clock: on Linux/mod_php it's CPU time and a blocking external API call can run long without tripping it, while PHP-FPM's request_terminate_timeout kills on wall-clock instead.
Common causes
- A loop over a large dataset doing per-row database writes or remote calls (imports, migrations, bulk product updates).
- A slow or hanging external API/HTTP request the script waits on with no timeout.
- An unindexed or expensive SQL query that takes tens of seconds to return.
- max_execution_time set too low (default 30s) for a legitimately long task.
- An infinite or near-infinite loop from a logic bug, where raising the limit only makes it run longer before dying.
How to fix it
- Find what's actually slowTurn on Query Monitor (WordPress) or add microtime() checkpoints around suspect blocks. A single missing DB index or one external API with no timeout is usually the whole problem, and fixing it beats raising the cap.
- Raise max_execution_time at the PHP levelIn php.ini set max_execution_time = 300, or via .htaccess add php_value max_execution_time 300 (Apache + mod_php only). On cPanel use MultiPHP INI Editor. For PHP-FPM/LiteSpeed also raise the FPM request_terminate_timeout / LiteSpeed timeouts, or the worker kills the request before PHP's own limit matters.
- Account for the proxy timeout tooBehind Nginx you'll also hit 504 Gateway Timeout from fastcgi_read_timeout (default 60s), and Cloudflare cuts requests at 100s. Raising PHP's limit alone won't help if the layer in front gives up first.
- Use set_time_limit(0) for one known-long scriptIn a CLI/cron job or a controlled long task, call set_time_limit(0) at the top to remove the cap for that script only. Don't do this on a normal web request, since a stuck request will pin a worker indefinitely.
- Offload long work to the backgroundMove imports, exports, and report generation to WP-Cron, a real system cron running WP-CLI, or a queue. Process in chunks so no single request needs more than a few seconds, which sidesteps every timeout layer at once.
Stop it recurring
Keep web requests short by pushing imports, exports, and external API work into chunked cron or queue jobs, and put explicit timeouts on every outbound HTTP call.