Skip to content

When on_shutdown function raises error, starlette doesn't catch it and uvicorn thinks that lifespan is not supported #1138

@mvolfik

Description

@mvolfik

Checklist

  • The bug is reproducible against the latest release and/or master.
  • There are no similar issues or pull requests to fix it yet.

Describe the bug

When one of the on_shutdown functions raises an error

To reproduce

from starlette.applications import Starlette

async def fail():
    raise Exception()

app = Starlette(on_shutdown=[fail])

(Doesn't matter if the function is async or not)

uvicorn app:app --log-level trace

Expected behavior

The exception is caught, reported, and Starlette shuts down properly

Actual behavior

Logs:

INFO:     Started server process [22310]
INFO:     Waiting for application startup.
TRACE:    ASGI [1] Started scope={'type': 'lifespan', 'asgi': {'version': '3.0', 'spec_version': '2.0'}}
TRACE:    ASGI [1] Receive {'type': 'lifespan.startup'}
TRACE:    ASGI [1] Send {'type': 'lifespan.startup.complete'}
INFO:     Application startup complete.
INFO:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
^C
INFO:     Shutting down
INFO:     Waiting for application shutdown.
TRACE:    ASGI [1] Receive {'type': 'lifespan.shutdown'}
TRACE:    ASGI [1] Raised exception
INFO:     ASGI 'lifespan' protocol appears unsupported.
INFO:     Application shutdown complete.
INFO:     Finished server process [22310]

Note that the TRACE messages are hidden, and all that is printed is "ASGI 'lifespan' protocol appears unsupported."

Debugging material

When I run uvicorn with --lifespan on, these logs appear:

Details
INFO:     Started server process [22568]
INFO:     Waiting for application startup.
TRACE:    ASGI [1] Started scope={'type': 'lifespan', 'asgi': {'version': '3.0', 'spec_version': '2.0'}}
TRACE:    ASGI [1] Receive {'type': 'lifespan.startup'}
TRACE:    ASGI [1] Send {'type': 'lifespan.startup.complete'}
INFO:     Application startup complete.
INFO:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
^C
INFO:     Shutting down
INFO:     Waiting for application shutdown.
TRACE:    ASGI [1] Receive {'type': 'lifespan.shutdown'}
TRACE:    ASGI [1] Raised exception
ERROR:    Exception in 'lifespan' protocol
Traceback (most recent call last):
  File "/tmp/issue/env/lib/python3.8/site-packages/uvicorn/lifespan/on.py", line 55, in main
    await app(scope, self.receive, self.send)
  File "/tmp/issue/env/lib/python3.8/site-packages/uvicorn/middleware/proxy_headers.py", line 45, in __call__
    return await self.app(scope, receive, send)
  File "/tmp/issue/env/lib/python3.8/site-packages/uvicorn/middleware/message_logger.py", line 65, in __call__
    raise exc from None
  File "/tmp/issue/env/lib/python3.8/site-packages/uvicorn/middleware/message_logger.py", line 61, in __call__
    await self.app(scope, inner_receive, inner_send)
  File "/tmp/issue/env/lib/python3.8/site-packages/starlette/applications.py", line 112, in __call__
    await self.middleware_stack(scope, receive, send)
  File "/tmp/issue/env/lib/python3.8/site-packages/starlette/middleware/errors.py", line 146, in __call__
    await self.app(scope, receive, send)
  File "/tmp/issue/env/lib/python3.8/site-packages/starlette/exceptions.py", line 58, in __call__
    await self.app(scope, receive, send)
  File "/tmp/issue/env/lib/python3.8/site-packages/starlette/routing.py", line 569, in __call__
    await self.lifespan(scope, receive, send)
  File "/tmp/issue/env/lib/python3.8/site-packages/starlette/routing.py", line 540, in lifespan
    async for item in self.lifespan_context(app):
  File "/tmp/issue/env/lib/python3.8/site-packages/starlette/routing.py", line 483, in default_lifespan
    await self.shutdown()
  File "/tmp/issue/env/lib/python3.8/site-packages/starlette/routing.py", line 528, in shutdown
    handler()
  File "./app.py", line 5, in fail
    raise Exception()
Exception
INFO:     Application shutdown complete.
INFO:     Finished server process [22568]

Environment

  • OS: Ubuntu 20.04.1 LTS
  • Python version: 3.8.5
click==7.1.2
h11==0.12.0
starlette==0.14.2
uvicorn==0.13.3

Additional context

Somebody likely ran into this here: https://stackoverflow.com/q/64512286/7292139

Metadata

Metadata

Assignees

No one assigned

    Labels

    featureNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions