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

FastAPI未捕获异常处理问题:如何返回自定义错误信息与状态码?

问题

我希望FastAPI应用始终在响应中返回详细错误信息,即使是未捕获的异常。已查阅官方文档,但仍无法满足需求。

示例中,端点/a和/b能返回正确的状态码与错误信息:/a直接抛出HTTPException,/b通过specific_error_handler处理ZeroDivisionError。

但端点/c表现不符合预期:抛出的TypeError本该触发generic_error_handler中的HTTPException,但客户端实际收到的是状态码500的Internal Server Error。

不想为每个端点都包裹try/except块,希望通过自定义异常处理实现未捕获错误的统一处理,该怎么做?

from fastapi import FastAPI, HTTPException

app = FastAPI()


@app.get("/a")
async def endpoint_a():
    raise HTTPException(status_code=501, detail="error occurred for endpoint a")


@app.get("/b")
async def endpoint_b():
    1 / 0  # unhandled ZeroDivisionError


@app.get("/c")
async def endpoint_c():
    1 + "1"  # unhandled TypeError


@app.exception_handler(ZeroDivisionError)
async def specific_error_handler(request, exc):
    raise HTTPException(status_code=501, detail=f"ZeroDivisionError occurred: {exc}")


@app.exception_handler(Exception)
async def generic_error_handler(request, exc):
    raise HTTPException(status_code=501, detail=f"unhandled Exception occurred: {exc}")
解决方案

问题出在自定义异常处理器中直接抛出HTTPException——FastAPI的异常处理器要求返回一个Response对象,而非再次抛出异常。当你在处理器里抛出HTTPException,它会被FastAPI默认的内部异常处理器捕获,返回500错误。

修改方法如下:

  • 在异常处理器中使用JSONResponse直接构造响应
  • 通用异常处理器中跳过HTTPException,交给默认处理器处理(保留主动抛出HTTPException的原有逻辑)

修改后的代码:

from fastapi import FastAPI, HTTPException
from fastapi.responses import JSONResponse
from starlette.requests import Request

app = FastAPI()


@app.get("/a")
async def endpoint_a():
    raise HTTPException(status_code=501, detail="error occurred for endpoint a")


@app.get("/b")
async def endpoint_b():
    1 / 0  # unhandled ZeroDivisionError


@app.get("/c")
async def endpoint_c():
    1 + "1"  # unhandled TypeError


@app.exception_handler(ZeroDivisionError)
async def specific_error_handler(request: Request, exc: ZeroDivisionError):
    return JSONResponse(
        status_code=501,
        content={"detail": f"ZeroDivisionError occurred: {exc}"}
    )


@app.exception_handler(Exception)
async def generic_error_handler(request: Request, exc: Exception):
    # 跳过HTTPException,交给默认处理器处理
    if isinstance(exc, HTTPException):
        return await app.default_exception_handler(request, exc)
    return JSONResponse(
        status_code=501,
        content={"detail": f"unhandled Exception occurred: {exc}"}
    )

关键说明

  1. 返回Response对象:所有自定义异常处理器必须返回Response的子类(如JSONResponse),这样才能直接将自定义响应返回给客户端。
  2. 保留默认HTTPException处理:在通用处理器中判断如果是HTTPException,则调用默认处理器,确保主动抛出HTTPException的场景仍能正常工作。
  3. 捕获所有未处理异常:Exception作为基类,会捕获所有未被更具体处理器处理的异常,包括TypeError这类内置异常。

这样修改后,/c端点抛出的TypeError会被generic_error_handler捕获,返回状态码501和自定义的详细错误信息,无需为每个端点添加try/except块。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 00:52:33