The Fix
Upgrade to version 0.24.0 or later.
Based on closed encode/httpx issue #2422 · 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%.
@@ -259,66 +259,56 @@ class LineDecoder:
Handles incrementally reading lines from text.
- Uses universal line decoding, supporting any of `\n`, `\r`, or `\r\n`
- as line endings, normalizing to `\n`.
+ Has the same behaviour as the stdllib splitlines, but handling the input iteratively.
def decode(self, text: str) -> typing.List[str]:
if self.buffer:
text = self.buffer + text
if text.endswith('\n'):
lines = text.splitlines()
self.buffer = ""
else:
lines = text.splitlines()
self.buffer = lines.pop()
return lines
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.24.0 or later.\nWhen NOT to use: This fix is not suitable if maintaining the original string slicing behavior is required.\n\n
Why This Fix Works in Production
- Trigger: LineDecoder is accidentally quadratic: iter_lines() seems to hang forever
- Mechanism: LineDecoder's string copying behavior is quadratic, causing significant delays in processing large chunks
- Why the fix works: upstream changes in 0.24.0 address the mechanism above.
- 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
- LineDecoder's string copying behavior is quadratic, causing significant delays in processing large chunks
- Surfaces as: LineDecoder is accidentally quadratic: iter_lines() seems to hang forever
Proof / Evidence
- GitHub issue: #2422
- Fix PR: https://github.com/encode/httpx/pull/2423
- First fixed release: 0.24.0
- Reproduced locally: No (not executed)
- Last verified: 2026-02-09
- Confidence: 0.70
- Did this fix it?: Yes (upstream fix exists)
- Own content ratio: 0.54
Discussion
High-signal excerpts from the issue thread (symptoms, repros, edge-cases).
“Just a quick follow-on, even if the chunks are already line-decoded, processing the 31MB file takes 6 seconds!! It would probably be a lot easier…”
“Actually, the unit tests clued me in that text.splitlines() is no good because you want to keep the delimiters in. Switched to re, and that…”
“Ah but okay, there's some whacky behaviours to do with CRLF and CR line-feeds, I will work on the PR as I get some time…”
“Actually, it's easier than that since splitlines() already returns a list”
Failure Signature (Search String)
- LineDecoder is accidentally quadratic: iter_lines() seems to hang forever
Error Message
Stack trace
Error Message
-------------
LineDecoder is accidentally quadratic: iter_lines() seems to hang forever
Minimal Reproduction
def decode(self, text: str) -> typing.List[str]:
if self.buffer:
text = self.buffer + text
if text.endswith('\n'):
lines = text.splitlines()
self.buffer = ""
else:
lines = text.splitlines()
self.buffer = lines.pop()
return lines
Why It Broke
LineDecoder's string copying behavior is quadratic, causing significant delays in processing large chunks
Fix Options (Details)
Option A — Upgrade to fixed release Safe default (recommended)
Upgrade to version 0.24.0 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/2423
First fixed release: 0.24.0
Last verified: 2026-02-09. Validate in your environment.
When NOT to Use This Fix
- This fix is not suitable if maintaining the original string slicing behavior is required.
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.
Version Compatibility Table
| Version | Status |
|---|---|
| 0.24.0 | Fixed |
Related Issues
No related fixes found.
Sources
We don’t republish the full GitHub discussion text. Use the links above for context.