Skip to content
🎉 Launch sale:50% off everything over $22 — automatically applied at checkout· ends Aug 2Shop the sale →
DevOps AI ToolKit
Newsletter
All guides
AI for NGINX By James Joyner IV · · 8 min read Last reviewed Jul 2026

Nginx Error: 'upstream sent invalid chunked response while reading upstream' — Cause and Fix

Quick answer

Fix nginx 'upstream sent invalid chunked response while reading upstream': the backend sends malformed Transfer-Encoding: chunked framing, causing 502.

  • #nginx
  • #web-server
  • #troubleshooting
  • #proxy
Free toolkit

Stuck on this NGINX error? Get the free incident triage checklist

A one-page PDF — the exact steps to isolate, fix, and verify a production error like this one. No spam, unsubscribe anytime.

What this error means

Nginx logs this when it is reading a proxied response that declares Transfer-Encoding: chunked but the chunk framing on the wire is malformed — a bad chunk-size line, a missing CRLF, or a truncated terminating chunk:

2026/07/12 14:22:41 [error] 2841#2841: *55210 upstream sent invalid chunked response while reading upstream, client: 203.0.113.7, server: example.com, request: "GET /api/stream HTTP/1.1", upstream: "http://10.0.3.20:8080/api/stream", host: "example.com"

Chunked transfer encoding frames a response body as a series of <hex-size>\r\n<data>\r\n blocks ending in a 0\r\n\r\n terminator. When nginx cannot parse that framing, it cannot trust the response, so it aborts the upstream read and returns 502 Bad Gateway to the client. The impact is failed responses — often on streaming or dynamically generated endpoints — that clients see as intermittent 502s despite the backend “working.”

How the server responds

  • Clients get 502 Bad Gateway on specific endpoints (often streaming or dynamically generated) while static or short responses are fine.
  • error.log shows upstream sent invalid chunked response while reading upstream with the offending upstream: and request:.
  • The backend’s own logs show a 200 and a completed response — the framing, not the status, is the problem.
  • Failures cluster on responses without a fixed Content-Length (the backend chose chunked encoding).
  • Capturing the raw upstream response shows a broken chunk-size line, missing \r\n, or a double Transfer-Encoding/Content-Length combination.
  • The problem appears or worsens when another proxy sits between nginx and the app and re-chunks the body.

Testing the server configuration

Confirm the error and pin down the exact upstream and path from the log:

sudo grep "invalid chunked response" /var/log/nginx/error.log | tail -n 20

Ask the backend directly, bypassing nginx, and inspect the response headers to see whether it uses chunked encoding and whether it also sends Content-Length:

# Talk straight to the upstream and show headers
curl -sS -D - -o /dev/null http://10.0.3.20:8080/api/stream

# Force HTTP/1.1 and watch the framing verbosely
curl -sS -v --http1.1 http://10.0.3.20:8080/api/stream >/dev/null

Look for the red flags: both Transfer-Encoding: chunked and Content-Length present, HTTP/1.0 in the status line alongside a chunked declaration, or a body that does not end in a clean 0\r\n\r\n. Capture the raw bytes if headers look fine but framing is suspect:

# Raw capture of the upstream conversation for offline inspection
sudo tcpdump -s0 -A -i any host 10.0.3.20 and port 8080 -w /tmp/upstream.pcap

Server configuration causes

  • Buggy application chunking — the backend hand-rolls chunked output (or a framework bug) and emits an incorrect chunk-size, a wrong CRLF, or an early terminator.
  • Double chunking — the app sets Transfer-Encoding: chunked and also writes chunk framing itself, or an intermediate proxy re-chunks an already-chunked body, producing nested/invalid frames.
  • HTTP/1.0 backend claiming chunked — chunked encoding is an HTTP/1.1 feature; a backend speaking 1.0 that advertises Transfer-Encoding: chunked produces a response nginx cannot parse under 1.0 semantics.
  • Conflicting Content-Length and Transfer-Encoding — a response carrying both headers is ambiguous; the framing nginx reads may not match either declaration.
  • A middlebox mangling the stream — a load balancer, WAF, or service mesh sidecar in front of the app alters the body or headers and corrupts chunk boundaries.

The fix

The correct fix is at the backend: emit valid chunked framing, or send a proper Content-Length instead of chunking. Remove any hand-written chunk framing when the framework already sets Transfer-Encoding: chunked, and never send both Transfer-Encoding and Content-Length.

On the nginx side, ensure it speaks HTTP/1.1 to the upstream so chunked responses are handled correctly, and strip conflicting hop-by-hop headers:

upstream backend {
    server 10.0.3.20:8080;
    keepalive 32;
}

server {
    location /api/ {
        proxy_pass http://backend;
        proxy_http_version 1.1;             # negotiate HTTP/1.1 with the backend
        proxy_set_header Connection "";      # clear "close" for keepalive reuse
    }
}

If the backend cannot produce valid chunked output, have it send an unchunked, buffered response with a Content-Length instead. You can also let nginx buffer the full response so it re-frames the body to the client with a length rather than passing chunks straight through:

location /api/ {
    proxy_pass http://backend;
    proxy_http_version 1.1;
    proxy_buffering on;                      # buffer upstream response (default)
    proxy_set_header Connection "";
}

Note that buffering does not repair genuinely malformed chunk bytes from the backend — it only helps when the issue is downstream re-chunking. A backend that emits corrupt frames must be fixed at the source. If an intermediate proxy is re-chunking, configure that hop to pass the body through unchanged.

Validate and reload after config changes (no restart needed for proxy directives):

sudo nginx -t && sudo systemctl reload nginx

Safe configuration practice

  • The authoritative fix is at the backend; nginx directives only change how the response is negotiated and buffered, not whether the upstream’s bytes are valid.
  • Never let a response carry both Content-Length and Transfer-Encoding: chunked — that ambiguity is a common source of this error and of request-smuggling risk.
  • Confirm proxy_http_version 1.1; wherever you rely on keepalive or chunked upstreams; the default HTTP/1.0 does not support chunked request/response semantics cleanly.
  • When a middlebox (WAF, mesh sidecar, LB) sits in front of the app, test with and without it to find which hop mangles the framing.
  • Streaming endpoints are the usual victims because they cannot know length upfront; give them extra scrutiny and consider server-sent events framing that is well tested.
  • Alert on a rise in invalid chunked response and correlated 502s so a backend deploy that breaks framing is caught quickly via your monitoring dashboard.

See the NGINX category for more guides.

Free download · 368-page PDF

Fixed it? Get 500 NGINX & DevOps AI prompts — free

500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.

  • 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
  • Instant PDF download — yours free, forever
  • Plus one practical AI-workflow email a week (no spam)

Single opt-in · unsubscribe anytime · no spam.

Did this fix your issue?

Free download · 368-page PDF

Get 500 Battle-Tested DevOps AI Prompts — Free

500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.

  • 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
  • Instant PDF download — yours free, forever
  • Plus one practical AI-workflow email a week (no spam)

Single opt-in · unsubscribe anytime · no spam.