emmett-framework / granian

A Rust HTTP server for Python applications

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Strange error with starlette / fastapi

aersam opened this issue · comments

Hi there

I've been trying to use startlette on some app of mine, and it worked well locally. In production however I get this strange error:

2024-06-07T11:34:36.7225565Z [ERROR] Application callable raised an exception
2024-06-07T11:34:36.7225739Z Traceback (most recent call last):
2024-06-07T11:34:36.7225904Z   File "/tmp/8dc86c846d0f82f/antenv/lib/python3.12/site-packages/granian/_futures.py", line 4, in future_watcher
2024-06-07T11:34:36.7226079Z     await inner(watcher.scope, watcher.proto)
2024-06-07T11:34:36.7226217Z   File "/tmp/8dc86c846d0f82f/antenv/lib/python3.12/site-packages/fastapi/applications.py", line 1054, in __call__
2024-06-07T11:34:36.7226374Z     await super().__call__(scope, receive, send)
2024-06-07T11:34:36.7226523Z   File "/tmp/8dc86c846d0f82f/antenv/lib/python3.12/site-packages/starlette/applications.py", line 123, in __call__
2024-06-07T11:34:36.7226660Z     await self.middleware_stack(scope, receive, send)
2024-06-07T11:34:36.7226814Z   File "/tmp/8dc86c846d0f82f/antenv/lib/python3.12/site-packages/starlette/middleware/errors.py", line 186, in __call__
2024-06-07T11:34:36.7226968Z     raise exc
2024-06-07T11:34:36.7227101Z   File "/tmp/8dc86c846d0f82f/antenv/lib/python3.12/site-packages/starlette/middleware/errors.py", line 164, in __call__
2024-06-07T11:34:36.7227252Z     await self.app(scope, receive, _send)
2024-06-07T11:34:36.7227387Z   File "/tmp/8dc86c846d0f82f/antenv/lib/python3.12/site-packages/starlette/middleware/base.py", line 189, in __call__
2024-06-07T11:34:36.7227541Z     with collapse_excgroups():
2024-06-07T11:34:36.7227683Z   File "/opt/python/3.12.2/lib/python3.12/contextlib.py", line 158, in __exit__
2024-06-07T11:34:36.7228228Z     self.gen.throw(value)
2024-06-07T11:34:36.7228459Z   File "/tmp/8dc86c846d0f82f/antenv/lib/python3.12/site-packages/starlette/_utils.py", line 93, in collapse_excgroups
2024-06-07T11:34:36.7228673Z     raise exc
2024-06-07T11:34:36.7228908Z   File "/tmp/8dc86c846d0f82f/antenv/lib/python3.12/site-packages/starlette/responses.py", line 261, in wrap
2024-06-07T11:34:36.7229135Z     await func()
2024-06-07T11:34:36.7229335Z   File "/tmp/8dc86c846d0f82f/antenv/lib/python3.12/site-packages/starlette/middleware/base.py", line 217, in stream_response
2024-06-07T11:34:36.7229559Z     return await super().stream_response(send)
2024-06-07T11:34:36.7229770Z            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2024-06-07T11:34:36.7229969Z   File "/tmp/8dc86c846d0f82f/antenv/lib/python3.12/site-packages/starlette/responses.py", line 250, in stream_response
2024-06-07T11:34:36.7230213Z     async for chunk in self.body_iterator:
2024-06-07T11:34:36.7230411Z   File "/tmp/8dc86c846d0f82f/antenv/lib/python3.12/site-packages/starlette/middleware/base.py", line 173, in body_stream
2024-06-07T11:34:36.7230571Z     assert message["type"] == "http.response.body"

My startup command is granian application:app --host 0.0.0.0 --port 8000 --workers 2 --interface asgi --loop asyncio

The route producing the error is very simple (starlette/fastapi)

rr = RedirectResponse(flow["auth_uri"])
rr.set_cookie("flow", json.dumps(flow, default=str), max_age=180)  # Temp cookie during auth flow
rr.headers.append("Cache-Control", "no-cache, max-age=0")

return rr

Any idea what could cause such an error?

This looks like #216.
Even after the long discussions and debugging, it's still unclear to me why Starlette fails in using its own response stream code (that assertion checks a ASGI message sent by starlette, not Granian).

I don't have any quick solution for this, I might spend some time trying to debug Starlette internals with Granian in the following weeks, but I'm not sure it will lead to any result.
Just a quick thing: any specific reason you're explicitly avoiding uvloop on a Unix OS? My gut tells me this is some concurrency issue with Starlette, uvloop might just automagically solve it.

The --loop was just an attempt to fix it, it's the same behavior. FYI: My Production Environment uses Linux and Python 3.12, it's an azure website

@aersam can you please provide a MRE including (but not limited to) the list of middlewares you're using?

The MRE is hard since I could not reproduce this, not on Windows nor on WSL. But I monkey-patched Starlette and have a better error message now :)

AssertionError: Unexpected message of type http.response.pathsend from class <class 'starlette.middleware.base.BaseHTTPMiddleware'>: {'type': 'http.response.pathsend', 'path': 'frontend_app/output/index.html'}

The MRE is hard since I could not reproduce this, not on Windows nor on WSL. But I monkey-patched Starlette and have a better error message now :)

AssertionError: Unexpected message of type http.response.pathsend from class <class 'starlette.middleware.base.BaseHTTPMiddleware'>: {'type': 'http.response.pathsend', 'path': 'frontend_app/output/index.html'}

Oh, that's actually a Starlette bug then!
Can you please open an issue in the Starlette repo mentioning this as the starting point?

cc @Kludex

I'm closing this since we now have encode/starlette#2613 and encode/starlette#2616