ERROR · 20 · VERIFIED 2026-10allwpcare.com/errors/502-bad-gateway/
Errors / 502-bad-gateway

502 Bad Gateway in WordPress

A 502 means nginx got no usable answer from PHP. Read its error log line, then restart PHP-FPM or fix its socket, header buffer or timeout.

The message you see
1−502 Bad Gateway
Last verified Oct 2026Tested with WordPress 7.1Applies to WordPress 7.1 (tested on nginx 1.31 with PHP-FPM 8.3 and on Apache 2.4 with PHP-FPM) · PHP 7.4+

Why it happens

  • PHP-FPM is stopped, crashed or restarting, so nginx finds nothing listening where it sends PHP requests. The nginx log says connect() failed (111: Connection refused) or (2: No such file or directory).
  • nginx may not open the PHP-FPM socket because of its owner or mode. The log says (13: Permission denied).
  • A PHP worker died while it was answering, for example killed by the system or stopped by PHP-FPM's request_terminate_timeout. The log says recv() failed (104: Connection reset by peer).
  • PHP sent response headers bigger than nginx's header buffer, often a very large cookie. The log says upstream sent too big header while reading response header from upstream.
  • A plugin or theme crashes the PHP process outright (a segmentation fault, not an ordinary PHP error).

How to fix it

Try the fixes in this order. Each one is independent: stop as soon as the error is gone.

FIX 01

Find out which part is broken

  1. Open a few addresses: your home page, /wp-login.php, and a picture or stylesheet. With PHP-FPM stopped on my test server, every PHP address returned 502 (/, /wp-login.php, /wp-admin/, /wp-json/), while /readme.html and an image still returned 200. If static files load and every PHP page fails, PHP-FPM is the problem. If only one URL fails, suspect one plugin or one big response.
  2. Look at the page. A plain white page headed "502 Bad Gateway" with nginx at the bottom comes from the web server, not from WordPress. WordPress never sends a 502 itself.
  3. Run a command that does not use the web server. WP-CLI runs PHP directly, so wp core version worked while the site returned 502. That shows WordPress and the database are fine and the fault is between the web server and PHP.
FIX 02

Read the nginx error log

  1. The log is usually /var/log/nginx/error.log. Many hosts show it under Logs in the hosting panel. In Docker, use docker logs on the nginx container.
  2. Find the line with the time you loaded the page, then use the table in this page to match it. The words in brackets after failed are the reason.
  3. If your host does not let you read the log, send them the time of the error and the page address and ask what their log says. That is all they need.
FIX 03

Start or restart PHP-FPM

  1. Use this for Connection refused or No such file or directory. On a server you manage, run sudo systemctl restart php8.3-fpm (the service is called php8.3-fpm on Debian and Ubuntu and often php-fpm elsewhere; use your PHP version). On managed hosting, use Restart PHP in the panel, or ask support.
  2. I tested this by stopping the PHP-FPM container and starting it again. The site went from 502 to 200 as soon as PHP-FPM was back, with no change to WordPress.
  3. If PHP-FPM stops again, read its own log. A line like child 11 exited on signal 9 (SIGKILL) means something killed the worker, often the system running out of memory.
FIX 04

Make the socket path and permissions match

  1. Use this for Permission denied, or for No such file or directory when PHP-FPM is running. Compare two lines. In the nginx site file, fastcgi_pass unix:/run/php/php-fpm.sock;. In the PHP-FPM pool file (for example /etc/php/8.3/fpm/pool.d/www.conf), listen = /run/php/php-fpm.sock. The paths must be identical.
  2. The pool's listen.owner, listen.group and listen.mode decide who may connect. The default mode is 0660, so the user nginx runs as must be that owner or in that group. In my test, the socket belonged to www-data with mode 0660 and nginx runs as nginx, so every PHP request failed with (13: Permission denied). Setting listen.owner and listen.group to the nginx user fixed it. Many setups use listen.owner = www-data and listen.group = www-data and run nginx as www-data, which also works.
  3. Restart PHP-FPM so it recreates the socket, then reload nginx with sudo nginx -s reload. Check the config first with sudo nginx -t.
  4. One extra thing I hit: a second PHP-FPM pool does not inherit WordPress's database settings if they come from environment variables. Pools clear the environment unless clear_env = no is set, and my first fixed pool showed "Error establishing a database connection" until I added it. That only matters on setups that pass the database details through the environment.
FIX 05

Raise nginx's header buffer for a too-big header

  1. Use this for upstream sent too big header. In the nginx location ~ \.php$ block, add fastcgi_buffer_size 32k; and fastcgi_buffers 8 16k;, then run sudo nginx -t and sudo nginx -s reload.
  2. I tested it with a 9,000-byte header: with nginx's default buffer it returned 502, and with fastcgi_buffer_size 32k the same URL returned 200. The nginx documentation says that if the first part of the response exceeds the buffer, "the response is considered invalid".
  3. Also find out why the header is so big. A plugin that sets a long cookie or many cookies is the usual reason. Fixing that is better than a bigger buffer.
FIX 06

Stop a PHP worker from being cut off

  1. Use this for recv() failed (104: Connection reset by peer) together with a PHP-FPM log line that says execution timed out ... terminating.
  2. In the pool file, request_terminate_timeout kills a worker that runs too long. It is off by default (0). If someone set it low, a slow page (a big import, a backup, an admin screen) is cut off and the visitor gets a 502. I set it to 2 seconds on a page that took 5, and got a 502 after 2.0 seconds.
  3. Raise the value, or fix what is slow. If instead nginx gives up waiting, that is a 504; see 504 Gateway Time-out. Compare with maximum execution time exceeded: that is PHP's own limit and WordPress shows it as an error message. A 502 from this cause means PHP-FPM cut the worker off before PHP could say anything.
FIX 07

Turn off the plugin that crashes PHP

  1. Use this when the 502 started right after a plugin or theme change, or when it only happens on some pages. With WP-CLI, wp plugin deactivate PLUGIN-NAME works while the site is down, because WP-CLI does not go through PHP-FPM. Without WP-CLI, rename the plugin's folder in wp-content/plugins by SFTP.
  2. I tested this with a plugin that ends the PHP process on request. With the plugin active the page returned 502. After wp plugin deactivate lab-crash it returned 200.
  3. Then turn plugins on one at a time to find the guilty one. See how to read the debug log for errors that WordPress can report. A real crash of the PHP process leaves nothing in debug.log; look in the PHP-FPM log instead.

A 502 Bad Gateway means the web server in front of WordPress asked PHP for the page and did not get a usable answer. The web server writes the reason in its error log, so read that first. The most common cause is PHP-FPM not running; restarting it clears it. WordPress itself never sends a 502.

What you see#

A plain white page with a large "502 Bad Gateway" heading and the web server's name and version under a line. It has no WordPress styling, because WordPress did not run.

A white page with the heading 502 Bad Gateway, a thin grey line, and the text nginx/1.31.8 below it.
The page on nginx 1.31.8 in front of PHP-FPM 8.3.36 serving WordPress 7.1.4, with PHP-FPM stopped.
Terminal
curl -i http://localhost:8990/
Output
HTTP/1.1 502 Bad GatewayServer: nginx/1.31.8Content-Type: text/htmlContent-Length: 157

Note what is missing: there is no X-Powered-By: PHP header. That header only comes from PHP, so its absence tells you PHP never answered.

How a 502 is made#

nginx does not run PHP. It passes each PHP request to PHP-FPM, a separate program, over a socket (a file such as /run/php/php-fpm.sock) or a network port. When that hand-off fails or the reply is not usable, nginx makes the 502 page itself and writes the reason in its error log. This is the "gateway" in the name: the web server is a gateway to PHP, and it got a bad answer. MDN defines it as a server acting as a gateway or proxy that "received an invalid response from the upstream server".

Five stacked steps. 1: the browser asks for a page. 2: nginx forwards the request to PHP-FPM. 3: the link to PHP-FPM fails because PHP-FPM is stopped, killed or sends a reply nginx rejects. 4: nginx logs why, for example connect() failed (111: Connection refused). 5: the visitor sees 502 Bad Gateway and WordPress never ran.
The 502 page is made by nginx. The reason is in nginx's error log, not on the page.

Match the log line to the fix#

I produced each of these on one test server and copied the log line. Server: nginx 1.31.8, PHP-FPM from PHP 8.3.36, WordPress 7.1.4, in Docker.

What I didnginx error log saysFix
Stopped PHP-FPM (nginx and PHP-FPM sharing one network address)connect() failed (111: Connection refused) while connecting to upstream ... upstream: "fastcgi://127.0.0.1:9000"Start PHP-FPM
Stopped PHP-FPM, socket setupconnect() to unix:/run/php/php-fpm.sock failed (2: No such file or directory)Start PHP-FPM, or fix the path
Socket owned by www-data, mode 0660, nginx running as nginxconnect() to unix:/run/php/php-fpm.sock failed (13: Permission denied)Set listen.owner and listen.group
PHP worker killed during the requestrecv() failed (104: Connection reset by peer) while reading response header from upstreamFind what kills it
9,000-byte response headerupstream sent too big header while reading response header from upstreamfastcgi_buffer_size
request_terminate_timeout = 2, page takes 5 secondsrecv() failed (104: Connection reset by peer)Raise or remove the timeout

The first line of the table needs a note. When I stopped a separate PHP-FPM container that nginx reached by its Docker name, the log said (113: Host is unreachable) instead of 111. That is a Docker detail; on a normal server, a stopped PHP-FPM gives 111 or 2.

PHP-FPM writes its own side of the story. For the killed worker:

PHP-FPM log
WARNING: [pool sock] child 11 exited on signal 9 (SIGKILL) after 18.706840 seconds from start

And for the timeout:

PHP-FPM log
WARNING: [pool sock] child 11, script '/var/www/html/index.php' (request: "GET /index.php?slow=1") execution timed out (2.021939 sec), terminatingWARNING: [pool sock] child 11 exited on signal 15 (SIGTERM) after 6.020629 seconds from start

502 or 504: who gave up#

A 502 means nginx got a bad answer or none because the link broke. A 504 means the link was fine but PHP took too long to answer. I tested both on the same page, which takes 5 seconds to run:

SettingResultnginx log
PHP-FPM request_terminate_timeout = 2502 after 2.0 srecv() failed (104: Connection reset by peer)
nginx fastcgi_read_timeout 2s504 after 2.0 supstream timed out (110: Operation timed out) while reading response header from upstream

The nginx default for fastcgi_read_timeout is 60 seconds. If your log says upstream timed out, you have a 504, not this error: see 504 Gateway Time-out.

A PHP error is not a 502#

I also tried an ordinary PHP fatal error (trigger_error with E_USER_ERROR) on the same nginx server. It returned 500, and the answer came from PHP. A crash that kills the worker returns 502. So a 502 with nothing in debug.log is normal: the process died before it could write anything. For fatal errors that PHP reports, see 500 Internal Server Error.

On Apache the same fault gives other codes#

Apache can also run PHP through PHP-FPM, using SetHandler "proxy:fcgi://..." in mod_proxy_fcgi. I pointed Apache 2.4.69 at the same PHP-FPM and repeated three faults. For these three, none gave a 502:

FaultApache statusApache error log
PHP-FPM stopped503(111)Connection refused: AH00957: FCGI: attempt to connect to ... failed and AH01079: failed to make connection to backend
Worker killed during the request503(104)Connection reset by peer: ... AH01075: Error dispatching request
9,000-byte response header500(22)Invalid argument: ... AH01075: Error dispatching request
A white page with the heading Service Unavailable, the text The server is temporarily unable to service your request due to maintenance downtime or capacity problems. Please try again later. and a footer reading Apache/2.4.69 (Debian) Server at localhost Port 8991.
What Apache 2.4.69 showed for a stopped PHP-FPM. The wording blames maintenance, but nobody started any.

So if your host runs Apache and you see a 502, the 502 may come from something else in front of it, such as a load balancer or a CDN (a service that sits between visitors and your server). I could not test those. The page footer or the Server response header names who answered; that is the quickest way to tell.

503 from the server is not maintenance mode#

The Apache page above says "Service Unavailable", the same status WordPress uses during an update. They are different things:

Server's 503 (PHP-FPM down)WordPress maintenance 503
Text"Service Unavailable ... due to maintenance downtime or capacity problems""Briefly unavailable for scheduled maintenance. Check back in a minute."
X-Powered-By: PHP headerNoYes
Retry-After headerNoRetry-After: 600
CausePHP-FPM or the backend is downA .maintenance file in the WordPress folder
FixStart PHP-FPMDelete .maintenance; see stuck maintenance mode

I made the second column by creating a .maintenance file on the nginx server: status 503, Retry-After: 600, and the site returned 200 as soon as I deleted the file. The maintenance 503 comes from wp_maintenance() in wp-includes/load.php. WordPress can send a 503 in a few other places too, but this is the one that matches the text above.

If the server is slow instead of dead, you have a 504 Gateway Time-out.

Things that will not fix it#

Clearing your browser cache or flushing your computer's DNS cache does not change a response that your server produced. Reloading the page is worth one try, because a PHP-FPM restart can cause a brief 502. If it lasts more than a minute, use the log.

Sources

  1. 502 Bad Gateway - HTTP, MDN · What the status means: a gateway or proxy got an invalid response from the upstream server.
  2. nginx ngx_http_fastcgi_module · fastcgi_buffer_size, fastcgi_buffers and fastcgi_read_timeout, with their defaults.
  3. PHP: PHP-FPM configuration · listen.owner, listen.group, listen.mode, request_terminate_timeout and clear_env.
  4. Apache mod_proxy_fcgi · How Apache is pointed at PHP-FPM with SetHandler proxy:fcgi. It does not list the status codes in the table above; those are from my own test.
  5. WordPress core: wp_maintenance() in load.php · Where WordPress sends the maintenance-mode 503, with Retry-After: 600.
Newsletter

One email when something breaks or changes.

New plugins and re-tested guides, about twice a month. Never a sales pitch.