You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

FastAPI 0.104.1中204状态码返回体断言错误求助

FastAPI 204状态码响应报错解决方案

问题背景

将FastAPI从0.85.2升级到0.104.1后,修改用户语言的PUT接口抛出错误:

AssertionError: Status code 204 must not have a response body

尝试将空return替换为return Response(status_code=HTTP_204_NO_CONTENT.value)后问题仍未解决。

接口代码

@router.put(
    "/api/v1/me/language",
    tags=["users"],
    responses={
        400: {"model": BadRequest},
        401: {"model": Unauthorized},
        403: {"model": Forbidden},
        404: {"model": NotFound},
        500: {"model": InternalServerError}
    },
    response_class=fastapi.responses.ORJSONResponse,
    status_code=204,
)
async def patch_me_users_language(
    request: Request, session=fastapi.Depends(get_db)
) -> NO_CONTENT_RESPONSE:
    content_bytes = await request.body()
    content = content_bytes.decode("utf-8").upper()

    if content in set(COUNTRIES):
        db_result = DBUser.get_by_uuid(
            request.state.user_uuid, session
        )
        if db_result:
            try:
                db_result.update({"language": content}, session)
                # Tried it already with 'return Response(status_code=HTTP_204_NO_CONTENT.value)'
                return
            except pydantic.error_wrappers.ValidationError as e:
                return http_err.UnprocessableEntity(detail=e.errors()).render()
        else:
            return http_err.InternalServerError(
                detail=f"User for this valid token does not exist."
            ).render()
    else:
        return http_err.UnprocessableEntity(
            detail=[
                {
                    "loc": ["body"],
                    "msg": "Expected the content to contain a valid language/country code",
                    "type": "value_error",
                }
            ]
        ).render()

错误类定义

class HttpErrors(pydantic.BaseModel):
    """
    Base class for HTTP error responses. The render method is used to translate instances of this class into
    fastapi.responses.ORJSONResponse responses.
    """
    status: int
    detail: str

    def render(self) -> fastapi.responses.ORJSONResponse:
        """
        Translates a class instance into a fastapi.responses.ORJSONResponse
        :return: fastapi.responses.ORJSONResponse
        """
        logger.info(f"Returned error response: status: {self.status}, msg: {self.content}")
        return fastapi.responses.ORJSONResponse(
            status_code=self.status,
            content=self.content()
        )

    def content(self):
        return {'detail': self.detail}

    def json_content(self):
        return json.dumps(self.content())


class BadRequest(HttpErrors):
    status = 400


class Unauthorized(HttpErrors):
    status = 401


class Forbidden(HttpErrors):
    status = 403


class NotFound(HttpErrors):
    status = 404


class UnprocessableEntity(pydantic.BaseModel):
    status = 422
    detail: List[dict]

    def render(self) -> fastapi.responses.ORJSONResponse:
        return fastapi.responses.ORJSONResponse(
            status_code=self.status,
            content={'detail': self.detail}
        )

解决方案

1. 移除全局response_class配置

204状态码要求响应无内容,而ORJSONResponse会默认尝试序列化响应体,即使返回空值,FastAPI新版本的严格校验会触发断言错误。去掉该配置后,FastAPI会自动为204状态码使用无内容的响应类:

@router.put(
    "/api/v1/me/language",
    tags=["users"],
    responses={
        400: {"model": BadRequest},
        401: {"model": Unauthorized},
        403: {"model": Forbidden},
        404: {"model": NotFound},
        500: {"model": InternalServerError}
    },
    status_code=204,  # 保留状态码配置
)

2. 明确返回无内容的Response对象

如果需要为错误响应保留ORJSONResponse,可以在成功分支明确返回不带内容的Response,确保没有任何响应体被生成:

from fastapi import Response, status

# 替换成功分支的return语句
return Response(
    status_code=status.HTTP_204_NO_CONTENT,
    content=None,
    media_type=None
)

3. 修正返回类型注解

204响应没有返回体,将原有的-> NO_CONTENT_RESPONSE改为-> None,避免FastAPI对返回类型的校验冲突:

async def patch_me_users_language(
    request: Request, session=fastapi.Depends(get_db)
) -> None:

原因说明

FastAPI 0.100+版本对HTTP规范的校验更加严格,严格遵循RFC 7231中204状态码的定义:响应必须不包含任何内容。旧版本中ORJSONResponse返回空值时可能不会生成响应体,但新版本会触发断言检查,确保204响应完全符合规范。

内容的提问来源于stack exchange,提问作者Stoecki

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 02:10:58