The Fix
pip install requests==2.27.0
Based on closed psf/requests issue #1360 · PR/commit linked
Production note: Watch p95/p99 latency and retry volume; timeouts can turn into retry storms and duplicate side-effects.
@@ -111,9 +111,11 @@ def resolve_redirects(self, resp, req, stream=False, timeout=None,
# Facilitate non-RFC2616-compliant 'location' headers
# (e.g. '/path/to/resource' instead of 'http://domain.tld/path/to/resource')
+ # Compliant with RFC3986, we percent encode the url.
if not urlparse(url).netloc:
- # Compliant with RFC3986, we percent encode the url.
Option A — Upgrade to fixed release\npip install requests==2.27.0\nWhen NOT to use: Do not use this fix if the server correctly follows RFC 2616.\n\n
Why This Fix Works in Production
- Trigger: Problem with 301-redirect
- Mechanism: The remote server is not following RFC 2616, causing issues with location headers
- Why the fix works: Ensures that location headers are always percent-encoded to handle non-compliant servers, resolving the issue with 301 redirects. (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 3.3 in real deployments (not just unit tests).
- The remote server is not following RFC 2616, causing issues with location headers
- Surfaces as: Traceback (most recent call last):\n File "C:\Dropbox\projects\Helpers\ph\.envwin32\lib\site-packages\requests\packages\urllib3\connectionpool.py", line 428, in urlopen\n…
Proof / Evidence
- GitHub issue: #1360
- Fix PR: https://github.com/psf/requests/pull/1361
- First fixed release: 2.27.0
- Reproduced locally: No (not executed)
- Last verified: 2026-02-07
- Confidence: 0.95
- Did this fix it?: Yes (upstream fix exists)
- Own content ratio: 0.34
Discussion
High-signal excerpts from the issue thread (symptoms, repros, edge-cases).
“Uh...can I ask you to uninstall and reinstall Requests? The TypeError that got thrown should have been impossible to hit, because it's inside a Try/Catch…”
“Ignore the first trace (I'll delete it), the key of the problem is:”
“Ah, ok, got it”
“Lucasa, thank you very much - now works fine”
Failure Signature (Search String)
- Problem with 301-redirect
Error Message
Stack trace
Error Message
-------------
Traceback (most recent call last):\n File "C:\Dropbox\projects\Helpers\ph\.envwin32\lib\site-packages\requests\packages\urllib3\connectionpool.py", line 428, in urlopen\n body=body, headers=headers)\n File "C:\Dropbox\projects\Helpers\ph\.envwin32\lib\site-packages\requests\packages\urllib3\connectionpool.py", line 290, in _make_request\n httplib_response = conn.getresponse()\n File "c:\Python33\lib\http\client.py", line 1143, in getresponse\n response.begin()\n File "c:\Python33\lib\http\client.py", line 354, in begin\n version, status, reason = self._read_status()\n File "c:\Python33\lib\http\client.py", line 324, in _read_status\n raise BadStatusLine(line)
Stack trace
Error Message
-------------
Traceback (most recent call last):\n File "C:\Dropbox\projects\Helpers\ph\.envwin32\lib\site-packages\requests\adapters.py", line 283, in send\n timeout=timeout\n File "C:\Dropbox\projects\Helpers\ph\.envwin32\lib\site-packages\requests\packages\urllib3\connectionpool.py", line 474, in urlopen\n raise MaxRetryError(self, url, e)
Stack trace
Error Message
-------------
Traceback (most recent call last):\n File "C:/Dropbox/projects/InfoStreams/test.py", line 25, in <module>\n allow_redirects=True)\n File "C:\Dropbox\projects\Helpers\ph\.envwin32\lib\site-packages\requests\api.py", line 55, in get\n return request('get', url, **kwargs)\n File "C:\Dropbox\projects\Helpers\ph\.envwin32\lib\site-packages\requests\api.py", line 44, in request\n return session.request(method=method, url=url, **kwargs)\n File "C:\Dropbox\projects\Helpers\ph\.envwin32\lib\site-packages\requests\sessions.py", line 345, in request\n resp = self.send(prep, **send_kwargs)\n File "C:\Dropbox\projects\Helpers\ph\.envwin32\lib\site-packages\requests\sessions.py", line 464, in send\n history = [resp for resp in gen] if allow_redirects else []\n File "C:\Dropbox\projects\Helpers\ph\.envwin32\lib\site-packages\requests\sessions.py", line 464, in <listcomp>\n history = [resp for resp in gen] if allow_redirects else []\n File "C:\Dropbox\projects\Helpers\ph\.envwin32\lib\site-packages\requests\sessions.py", line 154, in resolve_redirects\n allow_redirects=False,\n File "C:\Dropbox\projects\Helpers\ph\.envwin32\lib\site-packages\requests\sessions.py", line 448, in send\n r = adapter.send(request, **kwargs)\n File "C:\Dropbox\projects\Helpers\ph\.envwin32\lib\site-packages\requests\adapters.py", line 318, in send\n raise ConnectionError(e)
Environment
- Python: 3.3
What Broke
Requests fail with MaxRetryError when handling 301 redirects from non-compliant servers.
Why It Broke
The remote server is not following RFC 2616, causing issues with location headers
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.
Option D — Guard side-effects with OnceOnly Guardrail for side-effects
Mitigate duplicate external side-effects under retries/timeouts/agent loops by gating the operation before calling external systems.
- Place OnceOnly between your code/agent and real side-effects (Stripe, emails, CRM, APIs).
- Use a stable key per side-effect (e.g., customer_id + action + idempotency_key).
- Fail-safe: configure fail-open vs fail-closed based on blast radius and spend risk.
- This does NOT fix data corruption; it only prevents duplicate side-effects.
Show example snippet (optional)
from onceonly import OnceOnly
import os
once = OnceOnly(api_key=os.environ["ONCEONLY_API_KEY"], fail_open=True)
# Stable idempotency key per real side-effect.
# Use a request id / job id / webhook delivery id / Stripe event id, etc.
event_id = "evt_..." # replace
key = f"stripe:webhook:{event_id}"
res = once.check_lock(key=key, ttl=3600)
if res.duplicate:
return {"status": "already_processed"}
# Safe to execute the side-effect exactly once.
handle_event(event_id)
Fix reference: https://github.com/psf/requests/pull/1361
First fixed release: 2.27.0
Last verified: 2026-02-07. Validate in your environment.
When NOT to Use This Fix
- Do not use this fix if the server correctly follows RFC 2616.
- Do not use this to hide logic bugs or data corruption. Use it to block duplicate external side-effects and enforce tool permissions/spend caps.
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.