HTTP Content-Length Mismatch — Truncated or Extra Response
Fix Content-Length mismatch errors by letting the stack set the header, avoiding manual writes, and streaming with chunked transfer instead.
Symptoms
- The client errors with "premature end of Content-Length delimited message body"
- Downloads are truncated or hang near completion
- Setting Content-Length manually in the handler causes errors
Possible causes
- Content-Length is set manually to a value that differs from the actual body bytes
- The handler writes more or fewer bytes than declared
- A proxy re-compresses or strips bytes but keeps the original length
Diagnosis steps
Compare declared length with delivered bytes
curl -s -D - https://api.example.com/file -o out.bin && wc -c out.binInterpretation
A delivered size different from the Content-Length header proves a mismatch.
Look for manual length handling
grep -rn "Content-Length\|content-length" src/Interpretation
Manual length setting is the usual cause; let the framework compute it instead.
Root cause
When Content-Length is present, the client reads exactly that many bytes. If the server or a proxy sends a different number, the client reports a premature end or waits for bytes that never arrive.
Fix
Let the HTTP layer compute Content-Length from the actual body, avoid setting it manually, and for unknown-length streams use chunked transfer encoding (omit Content-Length) so the client reads until the terminating chunk.
Risk note
Combining compression with a manually set Content-Length is invalid; middleware that compresses must set length after compression or use chunked.
Verify the fix
Download the resource again and confirm the byte count matches the header; verify the full file hash is correct.
Symptoms
This debugging guide addresses “HTTP Content-Length Mismatch — Truncated or Extra Response”. Start from the symptoms, follow the ordered diagnostics, and confirm each hypothesis before moving on; the fix and verification steps then close the loop.
Observed symptoms include:
- The client errors with “premature end of Content-Length delimited message body”
- Downloads are truncated or hang near completion
- Setting Content-Length manually in the handler causes errors
Reproduce and Diagnose
Reproduce the failure in isolation before changing any code. Work through the checks below in order; each one narrows the search space.
Step 1: Compare declared length with delivered bytes
curl -s -D - https://api.example.com/file -o out.bin && wc -c out.bin
A delivered size different from the Content-Length header proves a mismatch.
Step 2: Look for manual length handling
grep -rn "Content-Length\|content-length" src/
Manual length setting is the usual cause; let the framework compute it instead.
Likely contributors, in order of frequency:
- Content-Length is set manually to a value that differs from the actual body bytes
- The handler writes more or fewer bytes than declared
- A proxy re-compresses or strips bytes but keeps the original length
Root Cause
When Content-Length is present, the client reads exactly that many bytes. If the server or a proxy sends a different number, the client reports a premature end or waits for bytes that never arrive.
The Fix
Let the HTTP layer compute Content-Length from the actual body, avoid setting it manually, and for unknown-length streams use chunked transfer encoding (omit Content-Length) so the client reads until the terminating chunk.
Watch out: Combining compression with a manually set Content-Length is invalid; middleware that compresses must set length after compression or use chunked.
// Express: let the framework set Content-Length from the body
res.json(payload); // length computed automatically
// streaming unknown-length response: use chunked (no Content-Length)
res.setHeader('Transfer-Encoding', 'chunked');
res.setHeader('Content-Type', 'text/event-stream');
stream.pipe(res); // ends with a terminating chunk
Verify and Prevent
Download the resource again and confirm the byte count matches the header; verify the full file hash is correct.
Once verified, add a regression test that reproduces the original symptom so the failure cannot silently return.
This class of failure is usually environmental rather than pure logic, so capture the exact command, the environment variables, and the working directory in your bug report. Reproduce it in the smallest possible script, then widen the scope only once the minimal case is understood. A short written checklist for this failure mode saves hours the next time it appears.