Jump to solution
Verify

The Fix

Upgrade to version 0.11.4 or later.

Based on closed Kludex/uvicorn issue #565 · 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
@@ -13,8 +13,8 @@ def get_version(package): Return package version as listed in `__version__` in `init.py`. """ - path = os.path.join(package, '__init__.py') - init_py = open(path, 'r', encoding='utf8').read() + path = os.path.join(package, "__init__.py")
repro.py
[2020-02-04 17:40:31 -0500] [37823] [ERROR] Exception in worker process Traceback (most recent call last): File "/Users/wagoodman/.pyenv/versions/3.7.4/envs/venv374/lib/python3.7/site-packages/gunicorn/arbiter.py", line 583, in spawn_worker worker.init_process() └ <uvicorn.workers.UvicornWorker object at 0x10b9f9110> File "/Users/wagoodman/.pyenv/versions/3.7.4/envs/venv374/lib/python3.7/site-packages/uvicorn/workers.py", line 57, in init_process super(UvicornWorker, self).init_process() │ └ <uvicorn.workers.UvicornWorker object at 0x10b9f9110> └ <class 'uvicorn.workers.UvicornWorker'> File "/Users/wagoodman/.pyenv/versions/3.7.4/envs/venv374/lib/python3.7/site-packages/gunicorn/workers/base.py", line 134, in init_process self.run() └ <uvicorn.workers.UvicornWorker object at 0x10b9f9110> File "/Users/wagoodman/.pyenv/versions/3.7.4/envs/venv374/lib/python3.7/site-packages/uvicorn/workers.py", line 66, in run loop.run_until_complete(server.serve(sockets=self.sockets)) │ │ └ <uvicorn.workers.UvicornWorker object at 0x10b9f9110> │ └ <uvicorn.main.Server object at 0x10bc80d90> └ <_UnixSelectorEventLoop running=False closed=False debug=False> File "/Users/wagoodman/.pyenv/versions/3.7.4/lib/python3.7/asyncio/base_events.py", line 579, in run_until_complete return future.result() └ <Task finished coro=<Server.serve() done, defined at /Users/wagoodman/.pyenv/versions/3.7.4/envs/venv374/lib/python3.7/site-pack... File "/Users/wagoodman/.pyenv/versions/3.7.4/envs/venv374/lib/python3.7/site-packages/uvicorn/main.py", line 403, in serve await self.shutdown(sockets=sockets) │ └ [<gunicorn.sock.TCPSocket object at 0x10bc77890>] └ <uvicorn.main.Server object at 0x10bc80d90> File "/Users/wagoodman/.pyenv/versions/3.7.4/envs/venv374/lib/python3.7/site-packages/uvicorn/main.py", line 533, in shutdown server.close() └ <Server sockets=[]> File "/Users/wagoodman/.pyenv/versions/3.7.4/lib/python3.7/asyncio/base_events.py", line 306, in close self._loop._stop_serving(sock) │ └ <gunicorn.sock.TCPSocket object at 0x10bc77890> └ <Server sockets=[]> File "/Users/wagoodman/.pyenv/versions/3.7.4/lib/python3.7/asyncio/selector_events.py", line 562, in _stop_serving self._remove_reader(sock.fileno()) │ └ <gunicorn.sock.TCPSocket object at 0x10bc77890> └ <_UnixSelectorEventLoop running=False closed=False debug=False> File "/Users/wagoodman/.pyenv/versions/3.7.4/envs/venv374/lib/python3.7/site-packages/gunicorn/sock.py", line 38, in __getattr__ return getattr(self.sock, name) │ └ 'fileno' └ <gunicorn.sock.TCPSocket object at 0x10bc77890> AttributeError: 'NoneType' object has no attribute 'fileno'
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\nUpgrade to version 0.11.4 or later.\nWhen NOT to use: This fix should not be applied if the shutdown behavior is expected to change for other components.\n\n

Why This Fix Works in Production

  • Trigger: [2020-02-04 17:40:31 -0500] [37823] [ERROR] Exception in worker process
  • Mechanism: Reverses the order during Server.shutdown() to ensure the server is closed first, followed by a safe close of any remaining sockets.
  • Why the fix works: Reverses the order during Server.shutdown() to ensure the server is closed first, followed by a safe close of any remaining sockets. (first fixed release: 0.11.4).

Why This Breaks in Prod

  • Shows up under Python 3.7 in real deployments (not just unit tests).
  • Surfaces as: [2020-02-04 17:40:31 -0500] [37823] [ERROR] Exception in worker process

Proof / Evidence

  • GitHub issue: #565
  • Fix PR: https://github.com/kludex/uvicorn/pull/566
  • First fixed release: 0.11.4
  • 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.31

Discussion

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

“Currently when running gunicorn + uvicorn (a suggested production deployment pattern), I get a exception on shutdown (on SIGTERM): This appears to be because sockets created by servers are explicitly closed before closing servers, however,”
Issue thread · issue description · source

Failure Signature (Search String)

  • [2020-02-04 17:40:31 -0500] [37823] [ERROR] Exception in worker process

Error Message

Stack trace
error.txt
Error Message ------------- [2020-02-04 17:40:31 -0500] [37823] [ERROR] Exception in worker process Traceback (most recent call last): File "/Users/wagoodman/.pyenv/versions/3.7.4/envs/venv374/lib/python3.7/site-packages/gunicorn/arbiter.py", line 583, in spawn_worker worker.init_process() └ <uvicorn.workers.UvicornWorker object at 0x10b9f9110> File "/Users/wagoodman/.pyenv/versions/3.7.4/envs/venv374/lib/python3.7/site-packages/uvicorn/workers.py", line 57, in init_process super(UvicornWorker, self).init_process() │ └ <uvicorn.workers.UvicornWorker object at 0x10b9f9110> └ <class 'uvicorn.workers.UvicornWorker'> File "/Users/wagoodman/.pyenv/versions/3.7.4/envs/venv374/lib/python3.7/site-packages/gunicorn/workers/base.py", line 134, in init_process self.run() └ <uvicorn.workers.UvicornWorker object at 0x10b9f9110> File "/Users/wagoodman/.pyenv/versions/3.7.4/envs/venv374/lib/python3.7/site-packages/uvicorn/workers.py", line 66, in run loop.run_until_complete(server.serve(sockets=self.sockets)) │ │ └ <uvicorn.workers.UvicornWorker object at 0x10b9f9110> │ └ <uvicorn.main.Server object at 0x10bc80d90> └ <_UnixSelectorEventLoop running=False closed=False debug=False> File "/Users/wagoodman/.pyenv/versions/3.7.4/lib/python3.7/asyncio/base_events.py", line 579, in run_u ... (truncated) ...

Minimal Reproduction

repro.py
[2020-02-04 17:40:31 -0500] [37823] [ERROR] Exception in worker process Traceback (most recent call last): File "/Users/wagoodman/.pyenv/versions/3.7.4/envs/venv374/lib/python3.7/site-packages/gunicorn/arbiter.py", line 583, in spawn_worker worker.init_process() └ <uvicorn.workers.UvicornWorker object at 0x10b9f9110> File "/Users/wagoodman/.pyenv/versions/3.7.4/envs/venv374/lib/python3.7/site-packages/uvicorn/workers.py", line 57, in init_process super(UvicornWorker, self).init_process() │ └ <uvicorn.workers.UvicornWorker object at 0x10b9f9110> └ <class 'uvicorn.workers.UvicornWorker'> File "/Users/wagoodman/.pyenv/versions/3.7.4/envs/venv374/lib/python3.7/site-packages/gunicorn/workers/base.py", line 134, in init_process self.run() └ <uvicorn.workers.UvicornWorker object at 0x10b9f9110> File "/Users/wagoodman/.pyenv/versions/3.7.4/envs/venv374/lib/python3.7/site-packages/uvicorn/workers.py", line 66, in run loop.run_until_complete(server.serve(sockets=self.sockets)) │ │ └ <uvicorn.workers.UvicornWorker object at 0x10b9f9110> │ └ <uvicorn.main.Server object at 0x10bc80d90> └ <_UnixSelectorEventLoop running=False closed=False debug=False> File "/Users/wagoodman/.pyenv/versions/3.7.4/lib/python3.7/asyncio/base_events.py", line 579, in run_until_complete return future.result() └ <Task finished coro=<Server.serve() done, defined at /Users/wagoodman/.pyenv/versions/3.7.4/envs/venv374/lib/python3.7/site-pack... File "/Users/wagoodman/.pyenv/versions/3.7.4/envs/venv374/lib/python3.7/site-packages/uvicorn/main.py", line 403, in serve await self.shutdown(sockets=sockets) │ └ [<gunicorn.sock.TCPSocket object at 0x10bc77890>] └ <uvicorn.main.Server object at 0x10bc80d90> File "/Users/wagoodman/.pyenv/versions/3.7.4/envs/venv374/lib/python3.7/site-packages/uvicorn/main.py", line 533, in shutdown server.close() └ <Server sockets=[]> File "/Users/wagoodman/.pyenv/versions/3.7.4/lib/python3.7/asyncio/base_events.py", line 306, in close self._loop._stop_serving(sock) │ └ <gunicorn.sock.TCPSocket object at 0x10bc77890> └ <Server sockets=[]> File "/Users/wagoodman/.pyenv/versions/3.7.4/lib/python3.7/asyncio/selector_events.py", line 562, in _stop_serving self._remove_reader(sock.fileno()) │ └ <gunicorn.sock.TCPSocket object at 0x10bc77890> └ <_UnixSelectorEventLoop running=False closed=False debug=False> File "/Users/wagoodman/.pyenv/versions/3.7.4/envs/venv374/lib/python3.7/site-packages/gunicorn/sock.py", line 38, in __getattr__ return getattr(self.sock, name) │ └ 'fileno' └ <gunicorn.sock.TCPSocket object at 0x10bc77890> AttributeError: 'NoneType' object has no attribute 'fileno'

Environment

  • Python: 3.7

What Broke

Exceptions occurred on shutdown when using gunicorn with uvicorn, leading to potential service disruptions.

Fix Options (Details)

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

Upgrade to version 0.11.4 or later.

When NOT to use: This fix should not be applied if the shutdown behavior is expected to change for other components.

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

Fix reference: https://github.com/kludex/uvicorn/pull/566

First fixed release: 0.11.4

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 should not be applied if the shutdown behavior is expected to change for other components.

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.
  • Make timeouts explicit and test them (unit + integration) to avoid silent behavior changes.
  • Instrument retries (attempt count + reason) and alert on spikes to catch dependency slowdowns.

Version Compatibility Table

VersionStatus
0.11.4 Fixed

Related Issues

No related fixes found.

Sources

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