The Fix
Upgrade to version 0.12.0 or later.
Based on closed Kludex/uvicorn issue #684 · PR/commit linked
Production note: This usually shows up under retries/timeouts. Treat it as a side-effect risk until you can verify behavior with a canary + real traffic.
@@ -62,7 +62,8 @@ def startup(self):
def restart(self):
self.mtimes = {}
- os.kill(self.process.pid, signal.SIGTERM)
+
+ self.process.terminate()
INFO: Application startup complete.
INFO: <Server sockets=[<socket.socket fd=592, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=6, laddr=('127.0.0.1', 8000)>]> is serving
WARNING: Detected file change in 'app\fast.py'. Reloading...
2020-05-28 03:23:58.519 | DEBUG | app.log:setup_logger:24 - setup logger
2020-05-28 03:23:58.748 | DEBUG | app.middlewares.sentry:setup_sentry:14 - setup sentry
WARNING: Executing <Task finished coro=<Server.serve() done, defined at C:\Users\Trim21\.venv\pol\lib\site-packages\uvicorn\main.py:384> exception=NameError("name 'a' is not defined") created at C:\Users\Trim21\scoop\apps\python37\3.7.7\lib\asyncio\base_events.py:566> took 0.782 seconds
Process SpawnProcess-2:
Traceback (most recent call last):
File "C:\Users\Trim21\scoop\apps\python37\3.7.7\lib\multiprocessing\process.py", line 297, in _bootstrap
self.run()
File "C:\Users\Trim21\scoop\apps\python37\3.7.7\lib\multiprocessing\process.py", line 99, in run
self._target(*self._args, **self._kwargs)
File "C:\Users\Trim21\.venv\pol\lib\site-packages\uvicorn\subprocess.py", line 62, in subprocess_started
target(sockets=sockets)
File "C:\Users\Trim21\.venv\pol\lib\site-packages\uvicorn\main.py", line 382, in run
loop.run_until_complete(self.serve(sockets=sockets))
File "C:\Users\Trim21\scoop\apps\python37\3.7.7\lib\asyncio\base_events.py", line 587, in run_until_complete
return future.result()
File "C:\Users\Trim21\.venv\pol\lib\site-packages\uvicorn\main.py", line 389, in serve
config.load()
File "C:\Users\Trim21\.venv\pol\lib\site-packages\uvicorn\config.py", line 288, in load
self.loaded_app = import_from_string(self.app)
File "C:\Users\Trim21\.venv\pol\lib\site-packages\uvicorn\importer.py", line 20, in import_from_string
module = importlib.import_module(module_str)
File "C:\Users\Trim21\scoop\apps\python37\3.7.7\lib\importlib\__init__.py", line 127, in import_module
return _bootstrap._gcd_import(name[level:], package, level)
File "<frozen importlib._bootstrap>", line 1006, in _gcd_import
File "<frozen importlib._bootstrap>", line 983, in _find_and_load
File "<frozen importlib._bootstrap>", line 967, in _find_and_load_unlocked
File "<frozen importlib._bootstrap>", line 677, in _load_unlocked
File "<frozen importlib._bootstrap_external>", line 728, in exec_module
File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
File ".\app\fast.py", line 111, in <module>
a
NameError: name 'a' is not defined
WARNING: Detected file change in 'app\fast.py'. Reloading...
Traceback (most recent call last):
File "C:\Users\Trim21\scoop\apps\python37\3.7.7\lib\runpy.py", line 193, in _run_module_as_main
"__main__", mod_spec)
File "C:\Users\Trim21\scoop\apps\python37\3.7.7\lib\runpy.py", line 85, in _run_code
exec(code, run_globals)
File "C:\Users\Trim21\.venv\pol\lib\site-packages\uvicorn\__main__.py", line 4, in <module>
uvicorn.main()
File "C:\Users\Trim21\.venv\pol\lib\site-packages\click\core.py", line 829, in __call__
return self.main(*args, **kwargs)
File "C:\Users\Trim21\.venv\pol\lib\site-packages\click\core.py", line 782, in main
rv = self.invoke(ctx)
File "C:\Users\Trim21\.venv\pol\lib\site-packages\click\core.py", line 1066, in invoke
return ctx.invoke(self.callback, **ctx.params)
File "C:\Users\Trim21\.venv\pol\lib\site-packages\click\core.py", line 610, in invoke
return callback(*args, **kwargs)
File "C:\Users\Trim21\.venv\pol\lib\site-packages\uvicorn\main.py", line 331, in main
run(*
... (truncated) ...
Re-run the minimal reproduction on your broken version, then apply the fix and re-run.
Option A — Upgrade to fixed release\nUpgrade to version 0.12.0 or later.\nWhen NOT to use: Do not use this fix if the application does not handle exceptions properly.\n\n
Why This Fix Works in Production
- Trigger: WARNING: Detected file change in 'app\fast.py'. Reloading...
- Mechanism: The child process exits abnormally after an exception, causing a PermissionError during reload
- Why the fix works: Fixes a terminate error in Windows when an exception occurs during the reload process. (first fixed release: 0.12.0).
- If left unfixed, retry loops can amplify load and turn a small outage into a cascade (thundering herd).
Why This Breaks in Prod
- Shows up under Python 3.8 in real deployments (not just unit tests).
- The child process exits abnormally after an exception, causing a PermissionError during reload
- Surfaces as: INFO: Application startup complete.
Proof / Evidence
- GitHub issue: #684
- Fix PR: https://github.com/kludex/uvicorn/pull/744
- First fixed release: 0.12.0
- 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.19
Discussion
High-signal excerpts from the issue thread (symptoms, repros, edge-cases).
“can you check if you got the same on python 3.8, I kind of remember there was a multiprocessing python bug, cant find it now”
“fixed by ignore OSError... I guess it's not a bug of multiprocessing, but the the process is not running. (sorry for my poor English)”
“ok I just reproduced, it's when it's raising an exception, totally misread hte case sorry :)”
“I checked the code, the problem here is that the child process exits abnormally after restarting. The main process did not detect this problem, so…”
Failure Signature (Search String)
- WARNING: Detected file change in 'app\fast.py'. Reloading...
Error Message
Stack trace
Error Message
-------------
INFO: Application startup complete.
INFO: <Server sockets=[<socket.socket fd=592, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=6, laddr=('127.0.0.1', 8000)>]> is serving
WARNING: Detected file change in 'app\fast.py'. Reloading...
2020-05-28 03:23:58.519 | DEBUG | app.log:setup_logger:24 - setup logger
2020-05-28 03:23:58.748 | DEBUG | app.middlewares.sentry:setup_sentry:14 - setup sentry
WARNING: Executing <Task finished coro=<Server.serve() done, defined at C:\Users\Trim21\.venv\pol\lib\site-packages\uvicorn\main.py:384> exception=NameError("name 'a' is not defined") created at C:\Users\Trim21\scoop\apps\python37\3.7.7\lib\asyncio\base_events.py:566> took 0.782 seconds
Process SpawnProcess-2:
Traceback (most recent call last):
File "C:\Users\Trim21\scoop\apps\python37\3.7.7\lib\multiprocessing\process.py", line 297, in _bootstrap
self.run()
File "C:\Users\Trim21\scoop\apps\python37\3.7.7\lib\multiprocessing\process.py", line 99, in run
self._target(*self._args, **self._kwargs)
File "C:\Users\Trim21\.venv\pol\lib\site-packages\uvicorn\subprocess.py", line 62, in subprocess_started
target(sockets=sockets)
File "C:\Users\Trim21\.venv\pol\lib\site-packages\uvicorn\main.py", line 382, in run
loop.run_until_complete(self.serve(sockets=sockets))
File "C:\Users\Trim21\scoop\apps\python37\3.7.7\lib\asyncio\base_events.py",
... (truncated) ...
Stack trace
Error Message
-------------
/home/lotso/PycharmProjects/uvicorn/venv/bin/python -m uvicorn app:app --reload
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
INFO: Started reloader process [15496] using watchgod
INFO: Started server process [15518]
INFO: Waiting for application startup.
INFO: ASGI 'lifespan' protocol appears unsupported.
INFO: Application startup complete.
WARNING: Detected file change in '['/home/lotso/PycharmProjects/uvicorn/app.py']'. Reloading...
INFO: Shutting down
INFO: Finished server process [15518]
Process SpawnProcess-2:
Traceback (most recent call last):
File "/home/lotso/.asdf/installs/python/3.8.5/lib/python3.8/multiprocessing/process.py", line 315, in _bootstrap
self.run()
File "/home/lotso/.asdf/installs/python/3.8.5/lib/python3.8/multiprocessing/process.py", line 108, in run
self._target(*self._args, **self._kwargs)
File "./uvicorn/subprocess.py", line 62, in subprocess_started
target(sockets=sockets)
File "./uvicorn/main.py", line 390, in run
loop.run_until_complete(self.serve(sockets=sockets))
File "uvloop/loop.pyx", line 1456, in uvloop.loop.Loop.run_until_complete
File "./uvicorn/main.py", line 397, in serve
config.load()
File "./uvicorn/config.py", line 278, in load
self.loaded_app = import_from_string(self.app)
File "./uvicorn/importer.py", line 20, in import_from_string
...
... (truncated) ...
Minimal Reproduction
INFO: Application startup complete.
INFO: <Server sockets=[<socket.socket fd=592, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=6, laddr=('127.0.0.1', 8000)>]> is serving
WARNING: Detected file change in 'app\fast.py'. Reloading...
2020-05-28 03:23:58.519 | DEBUG | app.log:setup_logger:24 - setup logger
2020-05-28 03:23:58.748 | DEBUG | app.middlewares.sentry:setup_sentry:14 - setup sentry
WARNING: Executing <Task finished coro=<Server.serve() done, defined at C:\Users\Trim21\.venv\pol\lib\site-packages\uvicorn\main.py:384> exception=NameError("name 'a' is not defined") created at C:\Users\Trim21\scoop\apps\python37\3.7.7\lib\asyncio\base_events.py:566> took 0.782 seconds
Process SpawnProcess-2:
Traceback (most recent call last):
File "C:\Users\Trim21\scoop\apps\python37\3.7.7\lib\multiprocessing\process.py", line 297, in _bootstrap
self.run()
File "C:\Users\Trim21\scoop\apps\python37\3.7.7\lib\multiprocessing\process.py", line 99, in run
self._target(*self._args, **self._kwargs)
File "C:\Users\Trim21\.venv\pol\lib\site-packages\uvicorn\subprocess.py", line 62, in subprocess_started
target(sockets=sockets)
File "C:\Users\Trim21\.venv\pol\lib\site-packages\uvicorn\main.py", line 382, in run
loop.run_until_complete(self.serve(sockets=sockets))
File "C:\Users\Trim21\scoop\apps\python37\3.7.7\lib\asyncio\base_events.py", line 587, in run_until_complete
return future.result()
File "C:\Users\Trim21\.venv\pol\lib\site-packages\uvicorn\main.py", line 389, in serve
config.load()
File "C:\Users\Trim21\.venv\pol\lib\site-packages\uvicorn\config.py", line 288, in load
self.loaded_app = import_from_string(self.app)
File "C:\Users\Trim21\.venv\pol\lib\site-packages\uvicorn\importer.py", line 20, in import_from_string
module = importlib.import_module(module_str)
File "C:\Users\Trim21\scoop\apps\python37\3.7.7\lib\importlib\__init__.py", line 127, in import_module
return _bootstrap._gcd_import(name[level:], package, level)
File "<frozen importlib._bootstrap>", line 1006, in _gcd_import
File "<frozen importlib._bootstrap>", line 983, in _find_and_load
File "<frozen importlib._bootstrap>", line 967, in _find_and_load_unlocked
File "<frozen importlib._bootstrap>", line 677, in _load_unlocked
File "<frozen importlib._bootstrap_external>", line 728, in exec_module
File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
File ".\app\fast.py", line 111, in <module>
a
NameError: name 'a' is not defined
WARNING: Detected file change in 'app\fast.py'. Reloading...
Traceback (most recent call last):
File "C:\Users\Trim21\scoop\apps\python37\3.7.7\lib\runpy.py", line 193, in _run_module_as_main
"__main__", mod_spec)
File "C:\Users\Trim21\scoop\apps\python37\3.7.7\lib\runpy.py", line 85, in _run_code
exec(code, run_globals)
File "C:\Users\Trim21\.venv\pol\lib\site-packages\uvicorn\__main__.py", line 4, in <module>
uvicorn.main()
File "C:\Users\Trim21\.venv\pol\lib\site-packages\click\core.py", line 829, in __call__
return self.main(*args, **kwargs)
File "C:\Users\Trim21\.venv\pol\lib\site-packages\click\core.py", line 782, in main
rv = self.invoke(ctx)
File "C:\Users\Trim21\.venv\pol\lib\site-packages\click\core.py", line 1066, in invoke
return ctx.invoke(self.callback, **ctx.params)
File "C:\Users\Trim21\.venv\pol\lib\site-packages\click\core.py", line 610, in invoke
return callback(*args, **kwargs)
File "C:\Users\Trim21\.venv\pol\lib\site-packages\uvicorn\main.py", line 331, in main
run(*
... (truncated) ...
Environment
- Python: 3.8
What Broke
Uvicorn fails to restart after an exception, leading to application downtime.
Why It Broke
The child process exits abnormally after an exception, causing a PermissionError during reload
Fix Options (Details)
Option A — Upgrade to fixed release Safe default (recommended)
Upgrade to version 0.12.0 or later.
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/744
First fixed release: 0.12.0
Last verified: 2026-02-09. Validate in your environment.
When NOT to Use This Fix
- Do not use this fix if the application does not handle exceptions properly.
Verify Fix
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
- 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
| Version | Status |
|---|---|
| 0.12.0 | Fixed |
Related Issues
No related fixes found.
Sources
We don’t republish the full GitHub discussion text. Use the links above for context.