The Fix
Upgrade to version 0.14.2 or later.
Based on closed encode/httpx issue #1168 · PR/commit linked
Production note: Most teams hit this during upgrades or environment changes. Roll out with a canary and smoke critical endpoints (health, OpenAPI/docs) before 100%.
@@ -613,6 +613,9 @@ def __init__(
def prepare(self) -> None:
for key, value in self.stream.get_headers().items():
+ # Ignore Transfer-Encoding if the Content-Length has been set explicitly.
+ if key.lower() == "transfer-encoding" and "content-length" in self.headers:
+ continue
>> import httpx
>> client = httpx.AsyncClient()
>> async def f():
... yield b'abcd'
...
>> r = await client.post('https://httpbin.org/post', data=f(), headers={'content-length': '4'})
>> r.json()
{'args': {}, 'data': 'abcd', 'files': {}, 'form': {}, 'headers': {'Accept': '*/*', 'Accept-Encoding': 'gzip, deflate', 'Host': 'httpbin.org', 'Transfer-Encoding': 'chunked', 'User-Agent': 'python-httpx/0.14.1', 'X-Amzn-Trace-Id': 'Root=1-5f3283ee-d5e67484ee0db0346804ce72'}, 'json': None, 'origin': 'x.x.x.x', 'url': 'https://httpbin.org/post'}
>> 'Content-Length' in r.json()['headers']
False
Re-run the minimal reproduction on your broken version, then apply the fix and re-run.
Option A — Upgrade to fixed release\nUpgrade to version 0.14.2 or later.\nWhen NOT to use: This fix should not be applied if the application relies on Transfer-Encoding for chunked uploads.\n\n
Why This Fix Works in Production
- Trigger: User-provided Content-Length header is missing from streaming requests
- Mechanism: The Content-Length header is ignored when Transfer-Encoding is also set for streaming requests
- Why the fix works: Addresses the issue of the Content-Length header being ignored in streaming requests by ensuring that the Transfer-Encoding header is not set when Content-Length is explicitly provided. (first fixed release: 0.14.2).
- If left unfixed, the same config can fail only in production (env differences), causing startup failures or partial feature outages.
Why This Breaks in Prod
- The Content-Length header is ignored when Transfer-Encoding is also set for streaming requests
- Production symptom (often without a traceback): User-provided Content-Length header is missing from streaming requests
Proof / Evidence
- GitHub issue: #1168
- Fix PR: https://github.com/encode/httpx/pull/1170
- First fixed release: 0.14.2
- Reproduced locally: No (not executed)
- Last verified: 2026-02-09
- Confidence: 0.85
- Did this fix it?: Yes (upstream fix exists)
- Own content ratio: 0.59
Discussion
High-signal excerpts from the issue thread (symptoms, repros, edge-cases).
“Labelling this as a good first issue, since there's hopefully enough into in the comment for someone to be able to resolve this.”
“Run your scripts and running Wireshark, httpx actually contains the content-length header: !image”
“@j178 Okay. It's possible that an intermediary could be stripping it before it gets to the server. Either way around the issue is valid, since…”
“To clarify, I noticed this while trying to make requests to an API that checks the presence of the Content-Length header (B2 API, to be…”
Failure Signature (Search String)
- User-provided Content-Length header is missing from streaming requests
- In other words, remove anything that doesn't make the bug go away.
Copy-friendly signature
Failure Signature
-----------------
User-provided Content-Length header is missing from streaming requests
In other words, remove anything that doesn't make the bug go away.
Error Message
Signature-only (no traceback captured)
Error Message
-------------
User-provided Content-Length header is missing from streaming requests
In other words, remove anything that doesn't make the bug go away.
Minimal Reproduction
>> import httpx
>> client = httpx.AsyncClient()
>> async def f():
... yield b'abcd'
...
>> r = await client.post('https://httpbin.org/post', data=f(), headers={'content-length': '4'})
>> r.json()
{'args': {}, 'data': 'abcd', 'files': {}, 'form': {}, 'headers': {'Accept': '*/*', 'Accept-Encoding': 'gzip, deflate', 'Host': 'httpbin.org', 'Transfer-Encoding': 'chunked', 'User-Agent': 'python-httpx/0.14.1', 'X-Amzn-Trace-Id': 'Root=1-5f3283ee-d5e67484ee0db0346804ce72'}, 'json': None, 'origin': 'x.x.x.x', 'url': 'https://httpbin.org/post'}
>> 'Content-Length' in r.json()['headers']
False
What Broke
Streaming requests fail to include user-defined Content-Length, causing issues with APIs expecting this header.
Why It Broke
The Content-Length header is ignored when Transfer-Encoding is also set for streaming requests
Fix Options (Details)
Option A — Upgrade to fixed release Safe default (recommended)
Upgrade to version 0.14.2 or later.
Use when you can deploy the upstream fix. It is usually lower-risk than long-lived workarounds.
Fix reference: https://github.com/encode/httpx/pull/1170
First fixed release: 0.14.2
Last verified: 2026-02-09. Validate in your environment.
When NOT to Use This Fix
- This fix should not be applied if the application relies on Transfer-Encoding for chunked uploads.
Verify Fix
Re-run the minimal reproduction on your broken version, then apply the fix and re-run.
Did This Fix Work in Your Case?
Quick signal helps us prioritize which fixes to verify and improve.
Prevention
- Add a CI check that diffs key outputs after upgrades (OpenAPI schema snapshots, JSON payload shapes, CLI output).
- Upgrade behind a canary and run integration tests against the canary before 100% rollout.
- Add a TLS smoke test that performs a real handshake in CI (include CA bundle validation and hostname checks).
- Alert on handshake failures by error string and endpoint to catch cert/CA changes quickly.
Version Compatibility Table
| Version | Status |
|---|---|
| 0.14.2 | Fixed |
Related Issues
No related fixes found.
Sources
We don’t republish the full GitHub discussion text. Use the links above for context.