Jump to solution
Verify

The Fix

Now that #5917 is merged, this should be set to go out on Monday with Requests 2.27.0.

Based on closed psf/requests issue #5855

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%.

Jump to Verify
repro.py
{ "implementation": { "name": "CPython", "version": "3.9.5" }, "platform": { "system": "Linux" }, "requests": { "version": "2.22.0" }, "urllib3": { "version": "1.25.3" }, "using_pyopenssl": false }
verify
Re-run the minimal reproduction on your broken version, then apply the fix and re-run.
fix.md
Option A — Apply the official fix\nNow that #5917 is merged, this should be set to go out on Monday with Requests 2.27.0.\nWhen NOT to use: Do not use if it changes public behavior or if the failure cannot be reproduced.\n\n

Why This Fix Works in Production

  • Trigger: proxy URLs without schemes break under Python 3.9
  • Mechanism: Now that #5917 is merged, this should be set to go out on Monday with Requests 2.27.0.
Production impact:
  • 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

  • Shows up under Python 3.9 in real deployments (not just unit tests).
  • Production symptom (often without a traceback): proxy URLs without schemes break under Python 3.9

Proof / Evidence

  • GitHub issue: #5855
  • Reproduced locally: No (not executed)
  • Last verified: 2026-02-04
  • Confidence: 0.00
  • Did this fix it?: No (no upstream fix linked)
  • Own content ratio: 0.67

Discussion

High-signal excerpts from the issue thread (symptoms, repros, edge-cases).

“Now that #5917 is merged, this should be set to go out on Monday with Requests 2.27.0. Resolving as fixed.”
@nateprewitt · 2021-12-30 · confirmation · source
“parse_url() is in the urllib3.util namespace so is supported. I encourage it's use as it's been vetted heavily.”
@sethmlarson · 2021-07-05 · source
“"soon 3.7 and 3.8" in the issue title isn't correct. The behavior change was present in 3.8.1 and 3.7.6 but reverted in 3.8.2 and 3.7.7.”
@timgraham · 2021-07-02 · source
“Oh good, I missed that, thanks. (There were a lot of bugs to read and I ended up skimming past that piece of history)”
@leifwalsh · 2021-07-02 · source

Failure Signature (Search String)

  • proxy URLs without schemes break under Python 3.9
  • In https://bugs.python.org/issue27657 it was decided to reverse an earlier decision about how `urllib.parse.urlparse` handles URLs that don't specify a scheme (e.g.
Copy-friendly signature
signature.txt
Failure Signature ----------------- proxy URLs without schemes break under Python 3.9 In https://bugs.python.org/issue27657 it was decided to reverse an earlier decision about how `urllib.parse.urlparse` handles URLs that don't specify a scheme (e.g. `example.org:80`). This behavior change is in Python 3.9.

Error Message

Signature-only (no traceback captured)
error.txt
Error Message ------------- proxy URLs without schemes break under Python 3.9 In https://bugs.python.org/issue27657 it was decided to reverse an earlier decision about how `urllib.parse.urlparse` handles URLs that don't specify a scheme (e.g. `example.org:80`). This behavior change is in Python 3.9.

Minimal Reproduction

repro.py
{ "implementation": { "name": "CPython", "version": "3.9.5" }, "platform": { "system": "Linux" }, "requests": { "version": "2.22.0" }, "urllib3": { "version": "1.25.3" }, "using_pyopenssl": false }

Environment

  • Python: 3.9

Fix Options (Details)

Option A — Apply the official fix

Now that #5917 is merged, this should be set to go out on Monday with Requests 2.27.0.

When NOT to use: Do not use if it changes public behavior or if the failure cannot be reproduced.

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.
Show example snippet (optional)
onceonly.py
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)

See OnceOnly SDK

When NOT to use: 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.

Fix reference: https://github.com/psf/requests/issues/5855

Get updates

We publish verified fixes weekly. No spam.

Subscribe

When NOT to Use This Fix

  • Do not use if it changes public behavior or if the failure cannot be reproduced.
  • 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.

Verify Fix

verify
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 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.

Related Issues

No related fixes found.

Sources

We don’t republish the full GitHub discussion text. Use the links above for context.