Jump to solution
Verify

The Fix

pip install urllib3==1.25

Based on closed urllib3/urllib3 issue #728 · PR/commit linked

Production note: Watch p95/p99 latency and retry volume; timeouts can turn into retry storms and duplicate side-effects.

Jump to Verify Open PR/Commit
@@ -217,7 +217,10 @@ def shutdown(self): def close(self): if self._makefile_refs < 1: - return self.connection.close() + try: + return self.connection.close()
repro.py
import urllib3.contrib.pyopenssl urllib3.contrib.pyopenssl.inject_into_urllib3() import urllib3, time conn = urllib3.connection_from_url('https://x.x.x.x/') print time.asctime() r = conn.request('GET', '/') r.close() time.sleep(15) # or 140, if you didn't reduce the timeout print time.asctime() r = conn.request('GET', '/') r.close() print "Problem did not reproduce :-("
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\nWhen NOT to use: This fix is not applicable if the connection handling logic is fundamentally altered.\n\n

Why This Fix Works in Production

  • Trigger: zato@prov:~$ /opt/zato/2.0.5/bin/py ~bcandler/test-https.py
  • Mechanism: Catches exceptions raised when closing connections that are dropped by the remote IIS server, preventing OpenSSL errors.
  • Why the fix works: Catches exceptions raised when closing connections that are dropped by the remote IIS server, preventing OpenSSL errors. (first fixed release: 1.25).

Why This Breaks in Prod

  • Shows up under Python 2.7.6 in real deployments (not just unit tests).
  • Surfaces as: zato@prov:~$ /opt/zato/2.0.5/bin/py ~bcandler/test-https.py

Proof / Evidence

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

Discussion

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

“I have been working on a standalone reproducer for this problem”
@candlerb · 2015-10-28 · source

Failure Signature (Search String)

  • zato@prov:~$ /opt/zato/2.0.5/bin/py ~bcandler/test-https.py

Error Message

Stack trace
error.txt
Error Message ------------- zato@prov:~$ /opt/zato/2.0.5/bin/py ~bcandler/test-https.py Wed Oct 28 11:22:52 2015 /opt/zato/2.0.5/eggs/urllib3-1.10.4-py2.7.egg/urllib3/connectionpool.py:768: InsecureRequestWarning: Unverified HTTPS request ... InsecureRequestWarning) Wed Oct 28 11:23:07 2015 Traceback (most recent call last): File "/opt/zato/2.0.5/bin/py", line 197, in <module> execfile(__file__) File "/home/bcandler/test-https.py", line 11, in <module> r = conn.request('GET', '/') File "/opt/zato/2.0.5/eggs/urllib3-1.10.4-py2.7.egg/urllib3/request.py", line 68, in request **urlopen_kw) File "/opt/zato/2.0.5/eggs/urllib3-1.10.4-py2.7.egg/urllib3/request.py", line 81, in request_encode_url return self.urlopen(method, url, **urlopen_kw) File "/opt/zato/2.0.5/eggs/urllib3-1.10.4-py2.7.egg/urllib3/connectionpool.py", line 533, in urlopen conn = self._get_conn(timeout=pool_timeout) File "/opt/zato/2.0.5/eggs/urllib3-1.10.4-py2.7.egg/urllib3/connectionpool.py", line 239, in _get_conn conn.close() File "/usr/lib/python2.7/httplib.py", line 786, in close self.sock.close() # close it manually... there may be other refs File "/opt/zato/2.0.5/eggs/urllib3-1.10.4-py2.7.egg/urllib3/contrib/pyopenssl.py", line 213, in close return self.connection.shutdown() File "/opt/zato/2.0.5/eggs/pyOpenSSL-0.15.1-py2.7.egg/OpenSSL/SSL.py", line 1522, in shutdown self._raise_s ... (truncated) ...

Minimal Reproduction

repro.py
import urllib3.contrib.pyopenssl urllib3.contrib.pyopenssl.inject_into_urllib3() import urllib3, time conn = urllib3.connection_from_url('https://x.x.x.x/') print time.asctime() r = conn.request('GET', '/') r.close() time.sleep(15) # or 140, if you didn't reduce the timeout print time.asctime() r = conn.request('GET', '/') r.close() print "Problem did not reproduce :-("

Environment

  • Python: 2.7.6

What Broke

Subsequent requests using the same connection can raise OpenSSL errors due to closed sockets.

Fix Options (Details)

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

pip install urllib3==1.25

When NOT to use: This fix is not applicable if the connection handling logic is fundamentally altered.

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/729

First fixed release: 1.25

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

  • This fix is not applicable if the connection handling logic is fundamentally altered.

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 Fixed

Related Issues

No related fixes found.

Sources

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