How HTTP Works

Debug guide · you're seeing

  • upstream sent too big header while reading response header from upstream
  • upstream sent too big header
  • 502 Bad Gateway

nginx Upstream Sent Too Big Header: Fix the 502

Fix nginx upstream sent too big header: measure response headers, size proxy or FastCGI buffers, and shrink oversized Set-Cookie and redirect headers.

Reviewed 6 min readintermediate12 sourcesTry itMarkdown
On this page

TL;DR: nginx ran out of room while reading the upstream response headers. Measure the failing response directly at the app, then increase proxy_buffer_size in the affected proxy_pass location; use fastcgi_buffer_size for PHP-FPM. More proxy_buffers alone will not fix it. Look for oversized Set-Cookie, Location and debug headers, especially on authentication routes.

What it means

The useful part of the nginx error log is:

upstream sent too big header while reading response header from upstream

nginx’s upstream parser logs this when the buffer is full and header parsing still needs more bytes. Its normal failure path returns 502 Bad Gateway, unless a retry succeeds or your configuration handles the error differently.

This is the opposite direction from Request Header Or Cookie Too Large. The app has already received the request. nginx is rejecting what the app sends back. Changing large_client_header_buffers or client_max_body_size addresses a different problem.

Measure the upstream response

Run this from somewhere that can reach the app directly, bypassing nginx. Replace http://upstream with the app’s address and the exact failing path:

curl -sD - -o /dev/null http://upstream | wc -c
# Example route on a local HTTP upstream:
curl -sS --http1.1 -D upstream.headers -o /dev/null \
  -H 'Host: example.com' 'http://127.0.0.1:3000/login'
wc -c < upstream.headers

-D dumps response headers; -o /dev/null discards the body. The count includes the status line and terminating blank line for this HTTP/1.1 response. Inspect curl’s errors too: zero bytes from a failed connection is not evidence of a small response.

Reproduce the method, Host, authentication and cookies of the failing request. An anonymous request may miss the session headers that trigger the 502. Do not substitute -I unless the failing request was HEAD, and do not add -L to this measurement: following redirects combines several response header blocks. Interim responses can also create extra blocks; inspect upstream.headers before treating its total as one response.

To rank the header lines by byte length without printing cookie or token values:

node -e 'const fs=require("node:fs"); const lines=fs.readFileSync("upstream.headers"); console.log(lines.toString("latin1").split("\r\n").filter(x=>x.includes(":")).map(x=>[Buffer.byteLength(x,"latin1")+2,x.slice(0,x.indexOf(":"))]).sort((a,b)=>b[0]-a[0]))'

Treat the captured file as sensitive. Measure each relevant response separately: the redirect into the identity provider, the callback, and the first request that creates or refreshes the session.

Find the growing header

  • Session cookies. A serialized session or token can produce a large Set-Cookie, and several cookies add to the same response header block. MDN describes each cookie as a separate Set-Cookie field. Splitting one session into more cookies does not reduce the total nginx must parse.
  • Authentication and OIDC redirects. Inspect both Location and Set-Cookie on the failing response. A long redirect URL contributes its whole header line to the buffer. OAuth2 Proxy documents multipart session cookies and recommends Redis for consistently large sessions, so only a small session ticket is stored in the browser.
  • Debug headers. Check any field containing serialized traces, query details or application state. Remove that payload from response headers and put diagnostic detail in server logs instead.

These are fields to measure, not a diagnosis from the status code. Use the byte counts to identify which one exceeds your route’s allowance.

Set the buffers for the upstream protocol

The nginx proxy module documents these defaults. The 4k or 8k choice depends on the platform’s memory page size:

DirectiveDefaultRole
proxy_buffer_size4k or 8kInitial response buffer, including headers
proxy_buffers8 4k or 8 8kResponse data buffers for one connection
proxy_busy_buffers_size8k or 16kCap on buffers busy sending while the upstream response is still being read

For proxy_pass, this illustrative configuration gives the header buffer 16 KiB. Choose a size above your measured header block, with room for normal variation:

location / {
    proxy_pass http://127.0.0.1:3000;
    proxy_buffer_size       16k;
    proxy_buffers           8 16k;
    proxy_busy_buffers_size 32k;
}

proxy_buffer_size is the line that fixes header capacity; the other two keep the buffer sizes compatible with it. nginx checks their relationship during configuration loading: the busy-buffer limit must be at least the larger of the header buffer and one body buffer, and fit within the body-buffer capacity minus one buffer. Run nginx -t before reloading.

proxy_buffering off still uses proxy_buffer_size to receive upstream data. It does not remove the header-size constraint. Likewise, hiding a header downstream does not remove nginx’s need to parse the upstream response first.

FastCGI and uwsgi

Change the directives matching the *_pass in the failing location. Put these illustrative settings alongside your existing upstream address and parameters:

# In a location using fastcgi_pass, such as PHP-FPM:
fastcgi_buffer_size       16k;
fastcgi_buffers           8 16k;
fastcgi_busy_buffers_size 32k;
# In a location using uwsgi_pass:
uwsgi_buffer_size       16k;
uwsgi_buffers           8 16k;
uwsgi_busy_buffers_size 32k;

The FastCGI and uwsgi modules each default to a 4k or 8k initial buffer, eight body buffers of that size, and an 8k or 16k busy-buffer limit. Changing proxy_buffer_size cannot enlarge a FastCGI or uwsgi response buffer.

gRPC

For grpc_pass, the relevant directive is grpc_buffer_size, also one memory page (4k or 8k) by default. The module passes responses synchronously and does not provide the grpc_buffers and grpc_busy_buffers_size pair:

# In the existing grpc_pass location:
grpc_buffer_size 16k;

Existing ingress-nginx deployments

The community ingress-nginx controller documents a 4k default and this annotation. Add it to the existing Ingress metadata:

metadata:
  annotations:
    nginx.ingress.kubernetes.io/proxy-buffer-size: "16k"

The same docs expose nginx.ingress.kubernetes.io/proxy-buffers-number and nginx.ingress.kubernetes.io/proxy-busy-buffers-size. Inspect the generated nginx configuration and controller logs after a change; do not assume that an accepted Kubernetes object proves nginx loaded it successfully.

As of this page’s review date, the project README says maintenance ended after March 2026, with no further bug fixes or security updates. Use this setting to repair an existing deployment while planning migration; the project explicitly advises against new deployments. These annotations belong to community ingress-nginx, not every controller with nginx in its name.

Raise the buffer, then stop the growth

A measured increase for a legitimate app response is a reasonable repair. Request-header limits govern bytes clients can submit; this response buffer governs what your upstream sends. The distinction does not make memory free: larger buffers across concurrent responses increase the capacity you must budget. Scope the change to the affected location rather than raising every route by habit.

Keep the response small anyway. Move session state out of cookies, stop reissuing redundant cookies, shorten redirect state where your authentication design allows it, and remove verbose diagnostic headers. A larger nginx buffer cannot guarantee that every downstream intermediary or browser will accept the response.

Reproduce and verify

nginx -t && nginx -s reload
nginx -T 2>&1 | grep -E 'proxy_buffer_size|fastcgi_buffer_size|uwsgi_buffer_size|grpc_buffer_size'
curl -sS -D - -o /dev/null 'https://example.com/failing-path'

Replay the same authenticated request through nginx and directly to the upstream. Success means the expected application response arrives, all intended cookies survive, and the matching error-log line stops appearing for that request. Check the login callback and session-refresh path as well as the first page load; otherwise you may have tested the smaller response.

Frequently asked questions

What does upstream sent too big header mean in nginx?

nginx filled its upstream header buffer before it could finish parsing the response headers. With no successful retry or custom error handling, the client receives 502 Bad Gateway. Measure the upstream response for the failing route and user.

Does proxy_buffers increase the response header limit?

No. For an HTTP proxy, proxy_buffer_size controls the initial response buffer. proxy_buffers holds response data after header parsing, and proxy_busy_buffers_size controls how much buffered data can be busy sending to the client.

What is the default proxy_buffer_size?

nginx defaults to one memory page, either 4k or 8k depending on the platform. The ingress-nginx controller documentation specifies its own 4k default. Check the configuration actually loaded on your server.

Does large_client_header_buffers fix this 502?

No. It controls headers arriving from the client. This error concerns headers coming back from the upstream application, so use the response-buffer directive for proxy_pass, fastcgi_pass, uwsgi_pass or grpc_pass.

Is raising the response header buffer a reasonable fix?

Yes, when a measured legitimate response needs more room. Apply the change to the affected route and account for memory under concurrency. Also remove unnecessary cookies, session state and debug headers so the response stops growing.

Sources

  1. nginx: proxy_buffer_size, proxy_buffers and proxy_busy_buffers_sizenginx.org
  2. nginx: FastCGI response buffersnginx.org
  3. nginx: uwsgi response buffersnginx.org
  4. nginx: gRPC response buffernginx.org
  5. nginx source: upstream header parsing and 502 handlinggithub.com
  6. nginx source: proxy buffer configuration constraintsgithub.com
  7. ingress-nginx: proxy buffer size annotationskubernetes.github.io
  8. ingress-nginx README: retirement and maintenance statusgithub.com
  9. OAuth2 Proxy: nginx integration and large session cookiesoauth2-proxy.github.io
  10. curl manual: --dump-header and --outputcurl.se
  11. MDN: Set-Cookiedeveloper.mozilla.org
  12. RFC 9110 Section 15.6.3: 502 Bad Gatewayrfc-editor.org

Keep going

Browse /search