Jump to solution
Verify

The Fix

pip install urllib3==1.25.11

Based on closed urllib3/urllib3 issue #1764 · 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%.

Jump to Verify Open PR/Commit
@@ -22,6 +22,7 @@ InvalidHeader, HTTPError, + SSLError, ) from .packages.six import string_types as basestring, PY3
repro.py
Traceback (most recent call last): File "/home/web/web/yandex/.env/lib/python3.5/site-packages/ioweb/network_service.py", line 177, in thread_network req, res, error, raise_network_error=False File "/home/web/web/yandex/.env/lib/python3.5/site-packages/ioweb/transport.py", line 310, in prepare_response self.read_with_timeout(req, res) File "/home/web/web/yandex/.env/lib/python3.5/site-packages/ioweb/transport.py", line 266, in read_with_timeout chunk = self.urllib3_response.read(chunk_size) File "/home/web/web/yandex/.env/lib/python3.5/site-packages/urllib3/response.py", line 507, in read data = self._fp.read(amt) if not fp_closed else b"" File "/usr/lib/python3.5/http/client.py", line 448, in read n = self.readinto(b) File "/usr/lib/python3.5/http/client.py", line 478, in readinto return self._readinto_chunked(b) File "/usr/lib/python3.5/http/client.py", line 573, in _readinto_chunked chunk_left = self._get_chunk_left() File "/usr/lib/python3.5/http/client.py", line 541, in _get_chunk_left chunk_left = self._read_next_chunk_size() File "/usr/lib/python3.5/http/client.py", line 501, in _read_next_chunk_size line = self.fp.readline(_MAXLINE + 1) File "/usr/lib/python3.5/socket.py", line 576, in readinto return self._sock.recv_into(b) File "/home/web/web/yandex/.env/lib/python3.5/site-packages/urllib3/contrib/pyopenssl.py", line 332, in recv_into raise ssl.SSLError("read error: %r" % e) ssl.SSLError: ("read error: Error([('SSL routines', 'ssl3_get_record', 'decryption failed or bad record mac')],)",)
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 urllib3==1.25.11\nWhen NOT to use: Do not use this fix if you require the original SSLError behavior for debugging.\n\n

Why This Fix Works in Production

  • Trigger: req, res, error, raise_network_error=False
  • Mechanism: urllib3 is allowing an SSLError to escape without proper wrapping
  • Why the fix works: Wraps BaseSSLError into SSLError during response reads to ensure proper exception handling. (first fixed release: 1.25.11).
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.5 in real deployments (not just unit tests).
  • urllib3 is allowing an SSLError to escape without proper wrapping
  • Surfaces as: Traceback (most recent call last):

Proof / Evidence

  • GitHub issue: #1764
  • Fix PR: https://github.com/urllib3/urllib3/pull/1939
  • First fixed release: 1.25.11
  • Reproduced locally: No (not executed)
  • Last verified: 2026-02-09
  • Confidence: 0.95
  • Did this fix it?: Yes (upstream fix exists)
  • Own content ratio: 0.29

Discussion

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

“@christopher-hesse I believe you're correct, we should be wrapping the BaseSSLError into a urllib3.exceptions.SSLError in line with the _error_catcher() contract of wrapping low-level Python exceptions…”
@sethmlarson · 2020-06-14 · source
“Hi @lorien! Can you please submit a simple reproducing script?”
@hodbn · 2020-04-27 · source
“It looks like urllib3.exceptions.SSLError says Raised when SSL certificate fails in an HTTPS connection”
@christopher-hesse · 2020-06-14 · source
“I've seen this error as well”
@christopher-hesse · 2020-06-14 · source

Failure Signature (Search String)

  • req, res, error, raise_network_error=False

Error Message

Stack trace
error.txt
Error Message ------------- Traceback (most recent call last): File "/home/web/web/yandex/.env/lib/python3.5/site-packages/ioweb/network_service.py", line 177, in thread_network req, res, error, raise_network_error=False File "/home/web/web/yandex/.env/lib/python3.5/site-packages/ioweb/transport.py", line 310, in prepare_response self.read_with_timeout(req, res) File "/home/web/web/yandex/.env/lib/python3.5/site-packages/ioweb/transport.py", line 266, in read_with_timeout chunk = self.urllib3_response.read(chunk_size) File "/home/web/web/yandex/.env/lib/python3.5/site-packages/urllib3/response.py", line 507, in read data = self._fp.read(amt) if not fp_closed else b"" File "/usr/lib/python3.5/http/client.py", line 448, in read n = self.readinto(b) File "/usr/lib/python3.5/http/client.py", line 478, in readinto return self._readinto_chunked(b) File "/usr/lib/python3.5/http/client.py", line 573, in _readinto_chunked chunk_left = self._get_chunk_left() File "/usr/lib/python3.5/http/client.py", line 541, in _get_chunk_left chunk_left = self._read_next_chunk_size() File "/usr/lib/python3.5/http/client.py", line 501, in _read_next_chunk_size line = self.fp.readline(_MAXLINE + 1) File "/usr/lib/python3.5/socket.py", line 576, in readinto return self._sock.recv_into(b) File "/home/web/web/yandex/.env/lib/python3.5/site-packages/urllib3/contrib/pyopenssl ... (truncated) ...

Minimal Reproduction

repro.py
Traceback (most recent call last): File "/home/web/web/yandex/.env/lib/python3.5/site-packages/ioweb/network_service.py", line 177, in thread_network req, res, error, raise_network_error=False File "/home/web/web/yandex/.env/lib/python3.5/site-packages/ioweb/transport.py", line 310, in prepare_response self.read_with_timeout(req, res) File "/home/web/web/yandex/.env/lib/python3.5/site-packages/ioweb/transport.py", line 266, in read_with_timeout chunk = self.urllib3_response.read(chunk_size) File "/home/web/web/yandex/.env/lib/python3.5/site-packages/urllib3/response.py", line 507, in read data = self._fp.read(amt) if not fp_closed else b"" File "/usr/lib/python3.5/http/client.py", line 448, in read n = self.readinto(b) File "/usr/lib/python3.5/http/client.py", line 478, in readinto return self._readinto_chunked(b) File "/usr/lib/python3.5/http/client.py", line 573, in _readinto_chunked chunk_left = self._get_chunk_left() File "/usr/lib/python3.5/http/client.py", line 541, in _get_chunk_left chunk_left = self._read_next_chunk_size() File "/usr/lib/python3.5/http/client.py", line 501, in _read_next_chunk_size line = self.fp.readline(_MAXLINE + 1) File "/usr/lib/python3.5/socket.py", line 576, in readinto return self._sock.recv_into(b) File "/home/web/web/yandex/.env/lib/python3.5/site-packages/urllib3/contrib/pyopenssl.py", line 332, in recv_into raise ssl.SSLError("read error: %r" % e) ssl.SSLError: ("read error: Error([('SSL routines', 'ssl3_get_record', 'decryption failed or bad record mac')],)",)

Environment

  • Python: 3.5

What Broke

Users experience unhandled SSLError during response reads, causing application crashes.

Why It Broke

urllib3 is allowing an SSLError to escape without proper wrapping

Fix Options (Details)

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

pip install urllib3==1.25.11

When NOT to use: Do not use this fix if you require the original SSLError behavior for debugging.

Use when you can deploy the upstream fix. It is usually lower-risk than long-lived workarounds.

Fix reference: https://github.com/urllib3/urllib3/pull/1939

First fixed release: 1.25.11

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

Get updates

We publish verified fixes weekly. No spam.

Subscribe

When NOT to Use This Fix

  • Do not use this fix if you require the original SSLError behavior for debugging.

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 CI check that diffs key outputs after upgrades (OpenAPI schema snapshots, JSON payload shapes, CLI output).
  • Upgrade behind a canary and run integration tests against the canary before 100% rollout.
  • 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.

Version Compatibility Table

VersionStatus
1.25.11 Fixed

Related Issues

No related fixes found.

Sources

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