The Fix
Improves error messaging when port binding fails on Windows, ensuring users receive a clear error message instead of an exception traceback.
Based on closed Kludex/uvicorn issue #435 · 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%.
@@ -225,7 +225,11 @@ def setup_event_loop(self):
sock = socket.socket()
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
- sock.bind((self.host, self.port))
+ try:
+ sock.bind((self.host, self.port))
$ uvicorn hello:app --host=0.0.0.0 --port=8000
email-validator not installed, email fields will be treated as str.
To install, run: pip install email-validator
INFO: Started server process [15384]
INFO: Waiting for application startup.
Traceback (most recent call last):
File "C:\Python36\lib\asyncio\base_events.py", line 1045, in create_server
sock.bind(sa)
OSError: [WinError 10048] Une seule utilisation de chaque adresse de socket (protocole/adresse r▒seau/port) est habituellement autoris▒e
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "c:\users\Th▒odore\Documents\prog\fastapi-test\.pyenv\Scripts\uvicorn-script.py", line 11, in <module>
load_entry_point('uvicorn==0.8.6', 'console_scripts', 'uvicorn')()
File "c:\users\Th▒odore\documents\prog\fastapi-test\.pyenv\lib\site-packages\click\core.py", line 764, in __call__
return self.main(*args, **kwargs)
File "c:\users\Th▒odore\documents\prog\fastapi-test\.pyenv\lib\site-packages\click\core.py", line 717, in main
rv = self.invoke(ctx)
File "c:\users\Th▒odore\documents\prog\fastapi-test\.pyenv\lib\site-packages\click\core.py", line 956, in invoke
return ctx.invoke(self.callback, **ctx.params)
File "c:\users\Th▒odore\documents\prog\fastapi-test\.pyenv\lib\site-packages\click\core.py", line 555, in invoke
return callback(*args, **kwargs)
File "c:\users\Th▒odore\documents\prog\fastapi-test\.pyenv\lib\site-packages\uvicorn\main.py", line 258, in main
run(**kwargs)
File "c:\users\Th▒odore\documents\prog\fastapi-test\.pyenv\lib\site-packages\uvicorn\main.py", line 279, in run
server.run()
File "c:\users\Th▒odore\documents\prog\fastapi-test\.pyenv\lib\site-packages\uvicorn\main.py", line 307, in run
loop.run_until_complete(self.serve(sockets=sockets))
File "C:\Python36\lib\asyncio\base_events.py", line 468, in run_until_complete
return future.result()
File "c:\users\Th▒odore\documents\prog\fastapi-test\.pyenv\lib\site-packages\uvicorn\main.py", line 322, in serve
await self.startup(sockets=sockets)
File "c:\users\Th▒odore\documents\prog\fastapi-test\.pyenv\lib\site-packages\uvicorn\main.py", line 377, in startup
create_protocol, host=config.host, port=config.port, ssl=config.ssl
File "C:\Python36\lib\asyncio\base_events.py", line 1049, in create_server
% (sa, err.strerror.lower()))
OSError: [Errno 10048] error while attempting to bind on address ('0.0.0.0', 8000): une seule utilisation de chaque adresse de socket (protocole/adresse r▒seau/port) est habituellement autoris▒e
ERROR: Task was destroyed but it is pending!
task: <Task pending coro=<LifespanOn.main() running at c:\users\Th▒odore\documents\prog\fastapi-test\.pyenv\lib\site-packages\uvicorn\lifespan\on.py:44> wait_for=<Future pending cb=[<TaskWakeupMethWrapper object at 0x0000019248B3EF78>()]>>
INFO: ASGI 'lifespan' protocol appears unsupported.
Re-run: uvicorn hello:app --host=0.0.0.0 --port=8000
Option A — Apply the official fix\nImproves error messaging when port binding fails on Windows, ensuring users receive a clear error message instead of an exception traceback.\nWhen NOT to use: Do not use this fix if the application is expected to handle multiple instances on the same port.\n\n
Why This Fix Works in Production
- Trigger: $ uvicorn hello:app --host=0.0.0.0 --port=8000
- Mechanism: Port binding fails on Windows due to socket address already in use
- 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
- Port binding fails on Windows due to socket address already in use
- Surfaces as: $ uvicorn hello:app --host=0.0.0.0 --port=8000
Proof / Evidence
- GitHub issue: #435
- Fix PR: https://github.com/kludex/uvicorn/pull/460
- Reproduced locally: No (not executed)
- Last verified: 2026-02-11
- Confidence: 0.70
- Did this fix it?: Yes (upstream fix exists)
- Own content ratio: 0.27
Discussion
High-signal excerpts from the issue thread (symptoms, repros, edge-cases).
“(Originally reported as tiangolo/fastapi#525, after having misdiagnosed this as a framework bug). ### Summary Attempting to start any application through Uvicorn, whether is actually supports lifespan or not, on a socket which is already be”
Failure Signature (Search String)
- $ uvicorn hello:app --host=0.0.0.0 --port=8000
Error Message
Stack trace
Error Message
-------------
$ uvicorn hello:app --host=0.0.0.0 --port=8000
email-validator not installed, email fields will be treated as str.
To install, run: pip install email-validator
INFO: Started server process [15384]
INFO: Waiting for application startup.
Traceback (most recent call last):
File "C:\Python36\lib\asyncio\base_events.py", line 1045, in create_server
sock.bind(sa)
OSError: [WinError 10048] Une seule utilisation de chaque adresse de socket (protocole/adresse r▒seau/port) est habituellement autoris▒e
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "c:\users\Th▒odore\Documents\prog\fastapi-test\.pyenv\Scripts\uvicorn-script.py", line 11, in <module>
load_entry_point('uvicorn==0.8.6', 'console_scripts', 'uvicorn')()
File "c:\users\Th▒odore\documents\prog\fastapi-test\.pyenv\lib\site-packages\click\core.py", line 764, in __call__
return self.main(*args, **kwargs)
File "c:\users\Th▒odore\documents\prog\fastapi-test\.pyenv\lib\site-packages\click\core.py", line 717, in main
rv = self.invoke(ctx)
File "c:\users\Th▒odore\documents\prog\fastapi-test\.pyenv\lib\site-packages\click\core.py", line 956, in invoke
return ctx.invoke(self.callback, **ctx.params)
File "c:\users\Th▒odore\documents\prog\fastapi-test\.pyenv\lib\site-packages\click\core.py", line 555, in invoke
return callback(*args, **kwargs
... (truncated) ...
Minimal Reproduction
$ uvicorn hello:app --host=0.0.0.0 --port=8000
email-validator not installed, email fields will be treated as str.
To install, run: pip install email-validator
INFO: Started server process [15384]
INFO: Waiting for application startup.
Traceback (most recent call last):
File "C:\Python36\lib\asyncio\base_events.py", line 1045, in create_server
sock.bind(sa)
OSError: [WinError 10048] Une seule utilisation de chaque adresse de socket (protocole/adresse r▒seau/port) est habituellement autoris▒e
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "c:\users\Th▒odore\Documents\prog\fastapi-test\.pyenv\Scripts\uvicorn-script.py", line 11, in <module>
load_entry_point('uvicorn==0.8.6', 'console_scripts', 'uvicorn')()
File "c:\users\Th▒odore\documents\prog\fastapi-test\.pyenv\lib\site-packages\click\core.py", line 764, in __call__
return self.main(*args, **kwargs)
File "c:\users\Th▒odore\documents\prog\fastapi-test\.pyenv\lib\site-packages\click\core.py", line 717, in main
rv = self.invoke(ctx)
File "c:\users\Th▒odore\documents\prog\fastapi-test\.pyenv\lib\site-packages\click\core.py", line 956, in invoke
return ctx.invoke(self.callback, **ctx.params)
File "c:\users\Th▒odore\documents\prog\fastapi-test\.pyenv\lib\site-packages\click\core.py", line 555, in invoke
return callback(*args, **kwargs)
File "c:\users\Th▒odore\documents\prog\fastapi-test\.pyenv\lib\site-packages\uvicorn\main.py", line 258, in main
run(**kwargs)
File "c:\users\Th▒odore\documents\prog\fastapi-test\.pyenv\lib\site-packages\uvicorn\main.py", line 279, in run
server.run()
File "c:\users\Th▒odore\documents\prog\fastapi-test\.pyenv\lib\site-packages\uvicorn\main.py", line 307, in run
loop.run_until_complete(self.serve(sockets=sockets))
File "C:\Python36\lib\asyncio\base_events.py", line 468, in run_until_complete
return future.result()
File "c:\users\Th▒odore\documents\prog\fastapi-test\.pyenv\lib\site-packages\uvicorn\main.py", line 322, in serve
await self.startup(sockets=sockets)
File "c:\users\Th▒odore\documents\prog\fastapi-test\.pyenv\lib\site-packages\uvicorn\main.py", line 377, in startup
create_protocol, host=config.host, port=config.port, ssl=config.ssl
File "C:\Python36\lib\asyncio\base_events.py", line 1049, in create_server
% (sa, err.strerror.lower()))
OSError: [Errno 10048] error while attempting to bind on address ('0.0.0.0', 8000): une seule utilisation de chaque adresse de socket (protocole/adresse r▒seau/port) est habituellement autoris▒e
ERROR: Task was destroyed but it is pending!
task: <Task pending coro=<LifespanOn.main() running at c:\users\Th▒odore\documents\prog\fastapi-test\.pyenv\lib\site-packages\uvicorn\lifespan\on.py:44> wait_for=<Future pending cb=[<TaskWakeupMethWrapper object at 0x0000019248B3EF78>()]>>
INFO: ASGI 'lifespan' protocol appears unsupported.
What Broke
Uvicorn aborts with misleading error message when port is already in use.
Why It Broke
Port binding fails on Windows due to socket address already in use
Fix Options (Details)
Option A — Apply the official fix
Improves error messaging when port binding fails on Windows, ensuring users receive a clear error message instead of an exception traceback.
Fix reference: https://github.com/kludex/uvicorn/pull/460
Last verified: 2026-02-11. Validate in your environment.
When NOT to Use This Fix
- Do not use this fix if the application is expected to handle multiple instances on the same port.
Verify Fix
Re-run: uvicorn hello:app --host=0.0.0.0 --port=8000
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.
Related Issues
No related fixes found.
Sources
We don’t republish the full GitHub discussion text. Use the links above for context.