[BUG] h11._util.LocalProtocolError: Can't send data when our state is ERROR
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:
- OS: Alpine Linux (docker
alpine:3.12) - Python 3.8.10
>>> print(fastapi_utils.__version__)
0.2.1
>>> print(fastapi.__version__)
0.92.0
>>> print(pydantic.utils.version_info())
pydantic version: 1.10.5
pydantic compiled: True
install path: /usr/lib/python3.8/site-packages/pydantic
python version: 3.8.10 (default, May 6 2021, 06:30:44) [GCC 9.3.0]
platform: Linux-4.19.0-23-amd64-x86_64-with
optional deps. installed: ['dotenv', 'email-validator', 'typing-extensions']
Additional context
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.
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