dmontagu / fastapi-utils

Reusable utilities for FastAPI
MIT License
1.92k stars 166 forks source link

[BUG] h11._util.LocalProtocolError: Can't send data when our state is ERROR #267

Closed m0wer closed 5 months ago

m0wer commented 1 year ago

Describe the bug A clear and concise description of what the bug is.

Full Traceback:

2023-02-20 07:51:32 ERROR [235][None] main.unhandled_exception_handler:151  While responding to POST UNDISCLOSED: Can't send data when our state is ERROR
Traceback (most recent call last):
  File "/usr/lib/python3.8/site-packages/starlette/middleware/errors.py", line 162, in __call__
    await self.app(scope, receive, _send)
  File "/usr/lib/python3.8/site-packages/starlette/middleware/base.py", line 109, in __call__
    await response(scope, receive, send)
  File "/usr/lib/python3.8/site-packages/starlette/responses.py", line 277, in __call__
    await wrap(partial(self.listen_for_disconnect, receive))
  File "/usr/lib/python3.8/site-packages/anyio/_backends/_asyncio.py", line 662, in __aexit__
    raise exceptions[0]
  File "/usr/lib/python3.8/site-packages/starlette/responses.py", line 273, in wrap
    await func()
  File "/usr/lib/python3.8/site-packages/starlette/middleware/base.py", line 134, in stream_response
    return await super().stream_response(send)
  File "/usr/lib/python3.8/site-packages/starlette/responses.py", line 255, in stream_response
    await send(
  File "/usr/lib/python3.8/site-packages/starlette/middleware/errors.py", line 159, in _send
    await send(message)
  File "/usr/lib/python3.8/site-packages/uvicorn/protocols/http/h11_impl.py", line 494, in send
    output = self.conn.send(event)
  File "/usr/lib/python3.8/site-packages/h11/_connection.py", line 512, in send
    data_list = self.send_with_data_passthrough(event)
  File "/usr/lib/python3.8/site-packages/h11/_connection.py", line 527, in send_with_data_passthrough
    raise LocalProtocolError("Can't send data when our state is ERROR")
h11._util.LocalProtocolError: Can't send data when our state is ERROR
2023-02-20 07:51:32 INFO  [236][None] timing.emit:132  TIMING: Wall: 3115.3ms | CPU:  348.7ms | UNDISCLOSED

To Reproduce Enable the timing middleware and use fastapi >= 0.90.0 (0.89.1 is the latest version where the error does not occur). Then call multiple endpoints concurrently and wait. The error does not always happen, but it's not hard to reproduce it with enough ~50-200 concurrent requests.

Expected behavior The error should not happen.

Environment:

Does not happen for previous versions of FastAPI or with the latest version 0.92.0 and the timing middleware disabled.

https://www.starlette.io/release-notes/ https://github.com/tiangolo/fastapi/releases

Something to look at (but might not be the cause since with starlette 0.23.0 it does already fail):

This can solve nuanced errors when using middlewares. Before Starlette 0.24.0, a new instance of each middleware class would be created when a new middleware was added. That normally was not a problem, unless the middleware class expected to be created only once, with only one instance, that happened in some cases. This upgrade would solve those cases (thanks @adriangb! Starlette PR #2017). Now the middleware class instances are created once, right before the first request (the first time the app is called). If you depended on that previous behavior, you might need to update your code. As always, make sure your tests pass before merging the upgrade.

Might be related to https://github.com/dmontagu/fastapi-utils/issues/266.

yuval9313 commented 5 months ago

I understand this has something to do with starlette and fastapi way of handling middleware, I could re export the middleware as route handler, but it doesn't fit the actual purpose of the route handler, I will close it since it doesn't relate to the actual utilities provided