The Fix
pip install requests==2.27.0
Based on closed psf/requests issue #4209 · 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%.
@@ -12,6 +12,9 @@ dev
**Bugfixes**
+- Fixed issue where Requests would raise ``ConnectionError`` instead of
+ ``SSLError`` when encoutering SSL problems when using urllib3 v1.22.
+
# starting with 2.18.1...
$ python -c 'import requests; requests.get("https://wrong.host.badssl.com")'
Traceback (most recent call last):
...
requests.exceptions.SSLError: hostname 'wrong.host.badssl.com' doesn't match either of '*.badssl.com', 'badssl.com'
$ pip install --upgrade requests
Collecting requests
...
Successfully installed requests-2.18.2 urllib3-1.22
$ python -c 'import requests; requests.get("https://wrong.host.badssl.com")'
Traceback (most recent call last):
...
requests.exceptions.ConnectionError: HTTPSConnectionPool(host='wrong.host.badssl.com', port=443): Max retries exceeded with url: / (Caused by SSLError(CertificateError("hostname 'wrong.host.badssl.com' doesn't match either of '*.badssl.com', 'badssl.com'",),))
Re-run: python -c 'import requests; requests.get("https://wrong.host.badssl.com")'
Re-run: pip install --upgrade requests
Option A — Upgrade to fixed release\npip install requests==2.27.0\nWhen NOT to use: This fix should not be applied if the behavior change is acceptable for your application.\n\n
Why This Fix Works in Production
- Trigger: # starting with 2.18.1...
- Mechanism: A breaking change in urllib3 caused SSLError to be raised as ConnectionError
- Why the fix works: Ensures that Requests raises SSLError instead of ConnectionError when encountering SSL problems with urllib3 v1.22. (first fixed release: 2.27.0).
- 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
- A breaking change in urllib3 caused SSLError to be raised as ConnectionError
- Surfaces as: # starting with 2.18.1...
Proof / Evidence
- GitHub issue: #4209
- Fix PR: https://github.com/psf/requests/pull/4210
- 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.42
Discussion
High-signal excerpts from the issue thread (symptoms, repros, edge-cases).
“Hrm, this breaking change happened because we made urllib3 retry on SSLError. In this case I think we need to add some custom code to…”
Failure Signature (Search String)
- # starting with 2.18.1...
Error Message
Stack trace
Error Message
-------------
# starting with 2.18.1...
$ python -c 'import requests; requests.get("https://wrong.host.badssl.com")'
Traceback (most recent call last):
...
requests.exceptions.SSLError: hostname 'wrong.host.badssl.com' doesn't match either of '*.badssl.com', 'badssl.com'
$ pip install --upgrade requests
Collecting requests
...
Successfully installed requests-2.18.2 urllib3-1.22
$ python -c 'import requests; requests.get("https://wrong.host.badssl.com")'
Traceback (most recent call last):
...
requests.exceptions.ConnectionError: HTTPSConnectionPool(host='wrong.host.badssl.com', port=443): Max retries exceeded with url: / (Caused by SSLError(CertificateError("hostname 'wrong.host.badssl.com' doesn't match either of '*.badssl.com', 'badssl.com'",),))
Minimal Reproduction
# starting with 2.18.1...
$ python -c 'import requests; requests.get("https://wrong.host.badssl.com")'
Traceback (most recent call last):
...
requests.exceptions.SSLError: hostname 'wrong.host.badssl.com' doesn't match either of '*.badssl.com', 'badssl.com'
$ pip install --upgrade requests
Collecting requests
...
Successfully installed requests-2.18.2 urllib3-1.22
$ python -c 'import requests; requests.get("https://wrong.host.badssl.com")'
Traceback (most recent call last):
...
requests.exceptions.ConnectionError: HTTPSConnectionPool(host='wrong.host.badssl.com', port=443): Max retries exceeded with url: / (Caused by SSLError(CertificateError("hostname 'wrong.host.badssl.com' doesn't match either of '*.badssl.com', 'badssl.com'",),))
What Broke
Developers experienced test failures due to unexpected ConnectionError instead of SSLError.
Why It Broke
A breaking change in urllib3 caused SSLError to be raised as ConnectionError
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/4210
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 behavior change is acceptable for your application.
Verify Fix
Re-run: python -c 'import requests; requests.get("https://wrong.host.badssl.com")'
Re-run: pip install --upgrade requests
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
| 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.