The Fix
pip install requests==2.27.0
Based on closed psf/requests issue #1572 · PR/commit linked
Production note: Watch p95/p99 latency and retry volume; timeouts can turn into retry storms and duplicate side-effects.
@@ -19,6 +19,7 @@
prepend_scheme_if_needed, get_auth_from_url, urldefragauth)
from .structures import CaseInsensitiveDict
+from .packages.urllib3.exceptions import ClosedPoolError
from .packages.urllib3.exceptions import ConnectTimeoutError
from .packages.urllib3.exceptions import HTTPError as _HTTPError
......
File "C:\Python27\lib\site-packages\requests\sessions.py", line 347, in get
return self.request('GET', url, **kwargs)
File "C:\Python27\lib\site-packages\requests\sessions.py", line 335, in request
resp = self.send(prep, **send_kwargs)
File "C:\Python27\lib\site-packages\requests\sessions.py", line 438, in send
r = adapter.send(request, **kwargs)
File "C:\Python27\lib\site-packages\requests\adapters.py", line 292, in send
timeout=timeout
File "C:\Python27\lib\site-packages\requests\packages\urllib3\connectionpool.py", line 423, in url
open
conn = self._get_conn(timeout=pool_timeout)
File "C:\Python27\lib\site-packages\requests\packages\urllib3\connectionpool.py", line 224, in _ge
t_conn
raise ClosedPoolError(self, "Pool is closed.")
ClosedPoolError: HTTPConnectionPool(host='......', port=80): Pool is closed.
Re-run the minimal reproduction on your broken version, then apply the fix and re-run.
Option A — Upgrade to fixed release\npip install requests==2.27.0\nWhen NOT to use: This fix should not be applied if the application relies on raw urllib3 exceptions.\n\n
Why This Fix Works in Production
- Mechanism: ClosedPoolError from urllib3 was not being caught and wrapped in requests
- Why the fix works: Catches and wraps the ClosedPoolError exception from urllib3, preventing it from leaking through the requests API. (first fixed release: 2.27.0).
- If left unfixed, this can cause silent data inconsistencies that propagate (bad cache entries, incorrect downstream decisions).
Why This Breaks in Prod
- Shows up under Python 2.7 in real deployments (not just unit tests).
- ClosedPoolError from urllib3 was not being caught and wrapped in requests
- Surfaces as: ......
Proof / Evidence
- GitHub issue: #1572
- Fix PR: https://github.com/psf/requests/pull/2674
- First fixed release: 2.27.0
- Reproduced locally: No (not executed)
- Last verified: 2026-02-07
- Confidence: 0.85
- Did this fix it?: Yes (upstream fix exists)
- Own content ratio: 0.21
Discussion
High-signal excerpts from the issue thread (symptoms, repros, edge-cases).
“I also got urllib3 exceptions passing through when use Session in several threads, trace:”
“I definitely agree with you and would agree that these should be wrapped. Could you give us stack-traces so we can find where they're bleeding…”
“Sorry I don't have stack traces readily available :/”
“No worries”
Error Message
Stack trace
Error Message
-------------
......
File "C:\Python27\lib\site-packages\requests\sessions.py", line 347, in get
return self.request('GET', url, **kwargs)
File "C:\Python27\lib\site-packages\requests\sessions.py", line 335, in request
resp = self.send(prep, **send_kwargs)
File "C:\Python27\lib\site-packages\requests\sessions.py", line 438, in send
r = adapter.send(request, **kwargs)
File "C:\Python27\lib\site-packages\requests\adapters.py", line 292, in send
timeout=timeout
File "C:\Python27\lib\site-packages\requests\packages\urllib3\connectionpool.py", line 423, in url
open
conn = self._get_conn(timeout=pool_timeout)
File "C:\Python27\lib\site-packages\requests\packages\urllib3\connectionpool.py", line 224, in _ge
t_conn
raise ClosedPoolError(self, "Pool is closed.")
ClosedPoolError: HTTPConnectionPool(host='......', port=80): Pool is closed.
Stack trace
Error Message
-------------
Traceback (most recent call last):
File "/home/krat/Projects/Grubhub/source/Pit/pit/web.py", line 52, in request
response = session.request(method, url, **kw)
File "/home/krat/.virtualenvs/grubhub/local/lib/python2.7/site-packages/requests/sessions.py", line 357, in request
resp = self.send(prep, **send_kwargs)
File "/home/krat/.virtualenvs/grubhub/local/lib/python2.7/site-packages/requests/sessions.py", line 460, in send
r = adapter.send(request, **kwargs)
File "/home/krat/.virtualenvs/grubhub/local/lib/python2.7/site-packages/requests/adapters.py", line 367, in send
r.content
File "/home/krat/.virtualenvs/grubhub/local/lib/python2.7/site-packages/requests/models.py", line 633, in content
self._content = bytes().join(self.iter_content(CONTENT_CHUNK_SIZE)) or bytes()
File "/home/krat/.virtualenvs/grubhub/local/lib/python2.7/site-packages/requests/models.py", line 572, in generate
decode_content=True):
File "/home/krat/.virtualenvs/grubhub/local/lib/python2.7/site-packages/requests/packages/urllib3/response.py", line 225, in stream
data = self.read(amt=amt, decode_content=decode_content)
File "/home/krat/.virtualenvs/grubhub/local/lib/python2.7/site-packages/requests/packages/urllib3/response.py", line 193, in read
e)
DecodeError: ('Received response with content-encoding: gzip, but failed to decode it.', error('Error -3 while deco
... (truncated) ...
Stack trace
Error Message
-------------
Traceback (most recent call last):
File "/home/oliver/wc/trunk/mtmCore/python/asagent/samplers/net/web.py", line 255, in process_url
resp = self.request(self.params.httpverb, url, data=data)
File "/home/oliver/wc/trunk/mtmCore/python/asagent/samplers/net/web.py", line 320, in request
verb, url, data=data))
File "abilisoft/requests/opt/abilisoft.com/thirdparty/requests/lib/python2.7/site-packages/requests/sessions.py", line 286, in prepare_request
File "abilisoft/requests/opt/abilisoft.com/thirdparty/requests/lib/python2.7/site-packages/requests/models.py", line 286, in prepare
File "abilisoft/requests/opt/abilisoft.com/thirdparty/requests/lib/python2.7/site-packages/requests/models.py", line 333, in prepare_url
File "abilisoft/requests/opt/abilisoft.com/thirdparty/requests/lib/python2.7/site-packages/requests/packages/urllib3/util.py", line 397, in parse_url
LocationParseError: Failed to parse: Failed to parse: fe80::5054:ff:fe5a:fc0
Minimal Reproduction
......
File "C:\Python27\lib\site-packages\requests\sessions.py", line 347, in get
return self.request('GET', url, **kwargs)
File "C:\Python27\lib\site-packages\requests\sessions.py", line 335, in request
resp = self.send(prep, **send_kwargs)
File "C:\Python27\lib\site-packages\requests\sessions.py", line 438, in send
r = adapter.send(request, **kwargs)
File "C:\Python27\lib\site-packages\requests\adapters.py", line 292, in send
timeout=timeout
File "C:\Python27\lib\site-packages\requests\packages\urllib3\connectionpool.py", line 423, in url
open
conn = self._get_conn(timeout=pool_timeout)
File "C:\Python27\lib\site-packages\requests\packages\urllib3\connectionpool.py", line 224, in _ge
t_conn
raise ClosedPoolError(self, "Pool is closed.")
ClosedPoolError: HTTPConnectionPool(host='......', port=80): Pool is closed.
Environment
- Python: 2.7
What Broke
Users experienced unhandled urllib3 exceptions causing application crashes.
Why It Broke
ClosedPoolError from urllib3 was not being caught and wrapped in requests
Fix Options (Details)
Option A — Upgrade to fixed release Safe default (recommended)
pip install requests==2.27.0
Use when you can deploy the upstream fix. It is usually lower-risk than long-lived workarounds.
Fix reference: https://github.com/psf/requests/pull/2674
First fixed release: 2.27.0
Last verified: 2026-02-07. Validate in your environment.
When NOT to Use This Fix
- This fix should not be applied if the application relies on raw urllib3 exceptions.
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
- Track RSS + object counts after deployments; alert on monotonic growth and GC pressure.
- Add a long-running test that repeats the failing call path and asserts stable memory.
- Make timeouts explicit and test them (unit + integration) to avoid silent behavior changes.
- Instrument retries (attempt count + reason) and alert on spikes to catch dependency slowdowns.
Version Compatibility Table
| Version | Status |
|---|---|
| 2.27.0 | Fixed |
Related Issues
No related fixes found.
Sources
We don’t republish the full GitHub discussion text. Use the links above for context.