Jump to solution
Verify

The Fix

pip install requests==2.32.4

Based on closed psf/requests issue #6934 · PR/commit linked

Jump to Verify Open PR/Commit
@@ -14,3 +14,4 @@ CN = Self-Signed Root CA # common name / your cert name [v3_ca] basicConstraints = critical, CA:true +keyUsage = critical, cRLSign, digitalSignature, keyCertSign diff --git a/tests/certs/expired/ca/ca.crt b/tests/certs/expired/ca/ca.crt index f08b2d67a5..2c8ebd44ae 100644
repro.py
====================================== short test summary info ======================================= FAILED tests/test_requests.py::TestRequests::test_proxy_error - Failed: DID NOT RAISE <class 'requests.exceptions.ProxyError'> FAILED tests/test_requests.py::TestRequests::test_pyopenssl_redirect - requests.exceptions.SSLError: HTTPSConnectionPool(host='127.0.0.1', port=36165): Max retries exce... FAILED tests/test_requests.py::TestRequests::test_auth_is_stripped_on_http_downgrade - requests.exceptions.SSLError: HTTPSConnectionPool(host='127.0.0.1', port=36165): Max retries exce... FAILED tests/test_requests.py::TestPreparingURLs::test_different_connection_pool_for_tls_settings_verify_bundle_unexpired_cert - requests.exceptions.SSLError: HTTPSConnectionPool(host='localhost', port=43243): Max retries exce... ============ 4 failed, 586 passed, 15 skipped, 1 xfailed, 18 warnings in 71.93s (0:01:11) ============
verify
Re-run the minimal reproduction on your broken version, then apply the fix and re-run.
fix.md
Option A — Upgrade to fixed release\npip install requests==2.32.4\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: Test regressions with urllib3 2.4.0 on Python 3.13
  • Mechanism: Tests fail due to missing key usage extension in the test CA certificate
  • Why the fix works: Adds a key usage extension to the test CA certificate, addressing issues with requests tests failing due to missing key usage. (first fixed release: 2.32.4).
Production impact:
  • If left unfixed, this can cause silent data inconsistencies that propagate (bad cache entries, incorrect downstream decisions).

Why This Breaks in Prod

  • Dependency interaction matters here: urllib3 v2.4.0.
  • Shows up under Python 3.13 in real deployments (not just unit tests).
  • Tests fail due to missing key usage extension in the test CA certificate
  • Production symptom (often without a traceback): Test regressions with urllib3 2.4.0 on Python 3.13

Proof / Evidence

  • GitHub issue: #6934
  • Fix PR: https://github.com/psf/requests/pull/6924
  • First fixed release: 2.32.4
  • Reproduced locally: No (not executed)
  • Last verified: 2026-02-08
  • Confidence: 0.85
  • Did this fix it?: Yes (upstream fix exists)
  • Own content ratio: 0.51

Discussion

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

“https://github.com/psf/requests/pull/6924 should fix test_different_connection_pool_for_tls_settings_verify_bundle_unexpired_cert Please check https://github.com/urllib3/urllib3/pull/3577#issuecomment-2765190031 too”
@illia-v · 2025-04-15 · source
“With the release of 2.32.4, this should be available in a published version. Resolving as there shouldn't be any remaining actions, please let us know…”
@nateprewitt · 2025-06-09 · source
“> #6924 should fix test_different_connection_pool_for_tls_settings_verify_bundle_unexpired_cert > > Please check urllib3/urllib3#3577 (comment) too Thanks! I can confirm that backporting 507409661335bd3dd8a7e39f04d07b42e519becc, 9ebebdef98a6aacfbedcf2ca61ba0ea”
@musicinmybrain · 2025-04-15 · source

Failure Signature (Search String)

  • Test regressions with urllib3 2.4.0 on Python 3.13
  • FAILED tests/test_requests.py::TestRequests::test_proxy_error - Failed: DID NOT RAISE <class 'requests.exceptions.ProxyError'>
Copy-friendly signature
signature.txt
Failure Signature ----------------- Test regressions with urllib3 2.4.0 on Python 3.13 FAILED tests/test_requests.py::TestRequests::test_proxy_error - Failed: DID NOT RAISE <class 'requests.exceptions.ProxyError'>

Error Message

Signature-only (no traceback captured)
error.txt
Error Message ------------- Test regressions with urllib3 2.4.0 on Python 3.13 FAILED tests/test_requests.py::TestRequests::test_proxy_error - Failed: DID NOT RAISE <class 'requests.exceptions.ProxyError'>

Minimal Reproduction

repro.py
====================================== short test summary info ======================================= FAILED tests/test_requests.py::TestRequests::test_proxy_error - Failed: DID NOT RAISE <class 'requests.exceptions.ProxyError'> FAILED tests/test_requests.py::TestRequests::test_pyopenssl_redirect - requests.exceptions.SSLError: HTTPSConnectionPool(host='127.0.0.1', port=36165): Max retries exce... FAILED tests/test_requests.py::TestRequests::test_auth_is_stripped_on_http_downgrade - requests.exceptions.SSLError: HTTPSConnectionPool(host='127.0.0.1', port=36165): Max retries exce... FAILED tests/test_requests.py::TestPreparingURLs::test_different_connection_pool_for_tls_settings_verify_bundle_unexpired_cert - requests.exceptions.SSLError: HTTPSConnectionPool(host='localhost', port=43243): Max retries exce... ============ 4 failed, 586 passed, 15 skipped, 1 xfailed, 18 warnings in 71.93s (0:01:11) ============

Environment

  • Python: 3.13
  • urllib3: 2.4.0

Why It Broke

Tests fail due to missing key usage extension in the test CA certificate

Fix Options (Details)

Option A — Upgrade to fixed release Safe default (recommended)

pip install requests==2.32.4

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

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)
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/pull/6924

First fixed release: 2.32.4

Last verified: 2026-02-08. Validate in your environment.

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

Version Compatibility Table

VersionStatus
2.32.4 Fixed

Related Issues

No related fixes found.

Sources

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