Fix Nginx 502 "upstream sent too big header"
A 502 caused by response headers larger than proxy_buffer_size. Read the error line, adjust buffer values, avoid combinations nginx rejects, and FastCGI.
The client gets a 502 and error.log shows the line below. The leading timestamp and PID and the middle client: and server: fields are shortened to …. For 502s with any other message, see this post.
… [error] … *1 upstream sent too big header while reading response header from upstream, … request: "HEAD / HTTP/1.1", upstream: "http://127.0.0.1:18602/", …[1] The cause is the response headers from the backend. The status line and headers must fit in one buffer of proxy_buffer_size; if they exceed it, the response is treated as invalid (nginx docs). The default is one memory page, 4k or 8k. The usual culprit is an oversized session or tracking Set-Cookie.
[2] Measure the headers by asking the backend directly, bypassing Nginx.
$ curl -sI http://127.0.0.1:18602/ | wc -c8333The test backend sends one 8KB Set-Cookie; the full headers were 8,333 bytes. You need a buffer larger than that.
[3] Set proxy_buffer_size above the header size, in the affected location (or server, http). With the 4k default this request returned 502; with 12k it returns 200.
location / { proxy_pass http://127.0.0.1:18602; proxy_buffer_size 12k;}# nginx -t && systemctl reload nginx$ curl -sI http://127.0.0.1:18601/ | head -1HTTP/1.1 200 OK[4] If you go higher, nginx -t can reject the result. proxy_buffer_size 16k; alone does not fit the default proxy_buffers (8 × 4k):
# nginx -tnginx: [emerg] "proxy_busy_buffers_size" must be less than the size of all "proxy_buffers" minus one buffer in /etc/nginx/conf.d/app.conf:4Set proxy_busy_buffers_size explicitly. This combination passed:
location / { proxy_pass http://127.0.0.1:18602; proxy_buffer_size 16k; proxy_busy_buffers_size 24k;}[5] The constraint between the values produces two different messages. Results from nginx -t (without proxy_buffers, it is 8 × 4k):
| Settings | Result |
|---|---|
proxy_buffer_size 12k; | passes |
proxy_buffer_size 16k; | must be less than the size of all "proxy_buffers" minus one buffer |
proxy_buffer_size 16k; proxy_busy_buffers_size 24k; | passes |
proxy_buffer_size 16k; proxy_busy_buffers_size 8k; | must be equal to or greater than the maximum of the value of "proxy_buffer_size" and one of the "proxy_buffers" |
proxy_buffer_size 16k; proxy_buffers 4 4k; proxy_busy_buffers_size 16k; | must be less than the size of all "proxy_buffers" minus one buffer |
proxy_busy_buffers_size must be at least the larger of proxy_buffer_size and one proxy_buffers buffer, and must stay below the total of proxy_buffers minus one buffer. With few buffers that range narrows, so raise the proxy_buffers count if it is rejected.
[6] Behind fastcgi_pass (PHP-FPM), raise fastcgi_buffer_size; the docs describe it the same way as proxy_buffer_size. If the config check rejects it, set fastcgi_busy_buffers_size too, as in step 4.
location ~ \.php$ { fastcgi_pass unix:/run/php/php-fpm.sock; fastcgi_buffer_size 16k;}[7] large_client_header_buffers is for request headers sent by the client. It does nothing here. With large_client_header_buffers 4 32k; in http, the same request still returned 502. That directive governs 414 and 400 errors.
Analyze your Nginx log in the browser ↗ — nothing is uploaded.