Ffile2fix
Sign in Get started

Fix "502 Bad Gateway" in Nginx

502 Bad Gateway
nginx

A 502 means the front server (Nginx, a load balancer or a CDN) forwarded the request to a backend such as PHP-FPM or a Node app and got an invalid response or none at all. The Nginx error log tells you which: the backend is down, the socket path is wrong, the process crashed mid-request or the response headers were too large.

Also appears as: upstream prematurely closed connection while reading response header from upstream · connect() to unix:/run/php/php8.3-fpm.sock failed (2: No such file or directory) while connecting to upstream · recv() failed (104: Connection reset by peer) while reading response header from upstream · upstream sent too big header while reading response header from upstream

Common causes

  • PHP-FPM or the application server is stopped or has crashed
  • fastcgi_pass or proxy_pass points to the wrong socket path, port or PHP version
  • The Nginx user cannot access the PHP-FPM socket because of listen.owner or listen.mode
  • PHP workers are killed mid-request by a segfault, OOM killer or request_terminate_timeout
  • Large response headers (many cookies) overflow fastcgi_buffer_size or proxy_buffer_size
  • A CDN such as Cloudflare cannot reach the origin or gets an invalid reply from it

How to fix it

  1. Read the Nginx error log. Run sudo tail -n 50 /var/log/nginx/error.log and reload the page. The upstream message (connection refused, no such file, prematurely closed, too big header) points to the exact fix.
  2. Check the backend is running. Run systemctl status php8.3-fpm (match your version) or check your Node/Gunicorn process. Start or restart it with sudo systemctl restart php8.3-fpm.
  3. Match the socket or port. Compare listen in /etc/php/8.3/fpm/pool.d/www.conf with fastcgi_pass in the Nginx site config. After a PHP upgrade the socket name usually changes, for example from php8.1-fpm.sock to php8.3-fpm.sock.
  4. Fix socket permissions. In the pool config set listen.owner = www-data, listen.group = www-data and listen.mode = 0660 (use nginx on RHEL-based systems), then restart PHP-FPM.
  5. Look for crashed workers. Check the PHP-FPM log and dmesg for segfaults or out-of-memory kills. Lower pm.max_children if the server is running out of RAM.
  6. Raise header buffers if needed. For "upstream sent too big header" increase fastcgi_buffer_size and fastcgi_buffers (or proxy_buffer_size and proxy_buffers), then run sudo nginx -t && sudo systemctl reload nginx.

Nginx server block

location ~ \.php$ {
    include snippets/fastcgi-php.conf;
    fastcgi_pass unix:/run/php/php8.3-fpm.sock;
    fastcgi_buffer_size 32k;
    fastcgi_buffers 16 16k;
}

How to stop it happening again

  • Update fastcgi_pass in the same change whenever you upgrade PHP
  • Size pm.max_children to available memory so the OOM killer does not reap workers
  • Monitor the backend service and restart it automatically with systemd
  • Run nginx -t before every reload

Frequently asked questions

What is the difference between 502 and 504?

A 502 means the backend gave a bad or empty response, often immediately. A 504 means the backend was reachable but took longer than the proxy timeout to answer.

Why do I get 502 only on some pages?

Usually those pages crash a PHP worker, exceed a memory limit or send very large headers. The error log entry for that exact request shows which.

Cloudflare shows a 502 but my server looks fine. Why?

If the Cloudflare-branded page appears, Cloudflare could not get a valid response from your origin. Check that the origin is reachable on the expected port and that its firewall allows Cloudflare IP ranges.