fastapi: Response content longer than Content-Length error for DELETE and NoContent
First Check
- I added a very descriptive title to this issue.
- I used the GitHub search to find a similar issue and didn’t find it.
- I searched the FastAPI documentation, with the integrated search.
- I already searched in Google “How to X in FastAPI” and didn’t find any information.
- I already read and followed all the tutorial in the docs and didn’t find an answer.
- I already checked if it is not related to FastAPI but to Pydantic.
- I already checked if it is not related to FastAPI but to Swagger UI.
- I already checked if it is not related to FastAPI but to ReDoc.
Commit to Help
- I commit to help with one of those options 👆
Example Code
from fastapi import FastAPI, status
app = FastAPI()
@app.delete("/", status_code=status.HTTP_204_NO_CONTENT)
def read_root():
return None
Description
Upon requesting above code I got expected response but my logs shows that there is an error in uvicorn. The problem exists for DELETE method and NoContent response status code (for HEAD there is no such problem)
ERROR: Exception in ASGI application
Traceback (most recent call last):
File "/home/user/PycharmProjects/sample_app/venv/lib/python3.9/site-packages/uvicorn/protocols/http/httptools_impl.py", line 372, in run_asgi
result = await app(self.scope, self.receive, self.send)
File "/home/user/PycharmProjects/sample_app/venv/lib/python3.9/site-packages/uvicorn/middleware/proxy_headers.py", line 75, in __call__
return await self.app(scope, receive, send)
File "/home/user/PycharmProjects/sample_app/venv/lib/python3.9/site-packages/fastapi/applications.py", line 269, in __call__
await super().__call__(scope, receive, send)
File "/home/user/PycharmProjects/sample_app/venv/lib/python3.9/site-packages/starlette/applications.py", line 124, in __call__
await self.middleware_stack(scope, receive, send)
File "/home/user/PycharmProjects/sample_app/venv/lib/python3.9/site-packages/starlette/middleware/errors.py", line 184, in __call__
raise exc
File "/home/user/PycharmProjects/sample_app/venv/lib/python3.9/site-packages/starlette/middleware/errors.py", line 162, in __call__
await self.app(scope, receive, _send)
File "/home/user/PycharmProjects/sample_app/venv/lib/python3.9/site-packages/starlette/exceptions.py", line 93, in __call__
raise exc
File "/home/user/PycharmProjects/sample_app/venv/lib/python3.9/site-packages/starlette/exceptions.py", line 82, in __call__
await self.app(scope, receive, sender)
File "/home/user/PycharmProjects/sample_app/venv/lib/python3.9/site-packages/fastapi/middleware/asyncexitstack.py", line 21, in __call__
raise e
File "/home/user/PycharmProjects/sample_app/venv/lib/python3.9/site-packages/fastapi/middleware/asyncexitstack.py", line 18, in __call__
await self.app(scope, receive, send)
File "/home/user/PycharmProjects/sample_app/venv/lib/python3.9/site-packages/starlette/routing.py", line 670, in __call__
await route.handle(scope, receive, send)
File "/home/user/PycharmProjects/sample_app/venv/lib/python3.9/site-packages/starlette/routing.py", line 266, in handle
await self.app(scope, receive, send)
File "/home/user/PycharmProjects/sample_app/venv/lib/python3.9/site-packages/starlette/routing.py", line 68, in app
await response(scope, receive, send)
File "/home/user/PycharmProjects/sample_app/venv/lib/python3.9/site-packages/starlette/responses.py", line 162, in __call__
await send({"type": "http.response.body", "body": self.body})
File "/home/user/PycharmProjects/sample_app/venv/lib/python3.9/site-packages/starlette/exceptions.py", line 79, in sender
await send(message)
File "/home/user/PycharmProjects/sample_app/venv/lib/python3.9/site-packages/starlette/middleware/errors.py", line 159, in _send
await send(message)
File "/home/user/PycharmProjects/sample_app/venv/lib/python3.9/site-packages/uvicorn/protocols/http/httptools_impl.py", line 501, in send
raise RuntimeError("Response content longer than Content-Length")
RuntimeError: Response content longer than Content-Length```
### Operating System
Linux
### Operating System Details
_No response_
### FastAPI Version
0.78.0
### Python Version
3.10
### Additional Context
_No response_
About this issue
- Original URL
- State: closed
- Created 2 years ago
- Reactions: 1
- Comments: 17 (6 by maintainers)
Commits related to this issue
- workaround for https://github.com/tiangolo/fastapi/issues/4939 — committed to hutschen/mv-tool-api by hutschen 2 years ago
This works as well:
Does FastAPI not have any regression tests? How is it that this wasn’t picked up when the starlette version was bumped?
OK, so I looked into this a bit and the issue looks to be related to a recent change in Starlette (see this discussion for a repro without FastAPI in the mix). It may be that Starlette used to suppress the content return on a JSONResponse if the response code was 204, but it no longer does.
I notice that, historically, there are a number of times when people have proposed adding code to FastAPI’s router to set the response class explicitly (to
Responserather thanJSONResponse) in case the response code is one of theSTATUS_CODES_WITH_NO_BODY. Given the amount of back-and-forth in the Starlette code around this, perhaps @tiangolo it’s worth FastAPI making this change? If you agree I’m happy to take a shot at it. If not, how about explicit documentation in FastAPI that if you plan to return no content you need to specify the response class.This seems to be an issue for me still on fastapi 0.82.0. It can be reproduced like this:
Visiting the page results in:
It’s worth noting that it’s the 3rd issue related to this topic created this week, so the current state of things is a loss of time for many users
I ran into this issue when using a custom response class that was returning a string with unicode characters instead of returning bytes. For example to reproduce:
This appears to be fixed somewhat in 0.79.0, as now if the status code is one that doesn’t allow content, it will explicitly set the response body to
b"", though in cases where you’re using another status code but want it to return no content, you still have to explicitly set theresponse_classtoResponse.