Skip to content

FastAPI 统一错误处理

接口项目不能只关注“正常返回”,还要关注“出错时怎么返回”。统一错误处理,就是给所有错误定规矩:格式统一、信息清楚、问题可定位、日志可追溯。

如果每个接口随手返回错误,前端要适配很多格式,后端排查也会很痛苦。

前端适配

所有接口使用同一套错误格式,前端不用为每个接口单独写解析逻辑。

问题定位

通过错误码、错误信息和字段详情,快速判断问题来自参数、业务、系统还是框架。

用户体验

对用户返回可理解的提示,避免直接暴露堆栈、数据库错误等技术细节。

日志追溯

每个请求带上 request_id,线上出问题时可以把前端反馈和后端日志对应起来。

一句话:统一错误处理就是给所有错误“定规矩”,统一格式、规则和记录方式。

目标 含义 实现方式
可读 用户和前端能看懂错误,不被技术术语淹没 标准响应结构 + 友好提示文案
可定位 开发者能快速识别错误来源 错误码分类 + 明确错误字段
可追溯 能查到完整请求上下文和报错链路 request_id + 统一日志记录

统一错误处理可以按这条链路理解:

  1. 客户端发送请求:前端或调用方发起 HTTP 请求。

  2. 生成请求标识:FastAPI 应用为请求生成 request_id,并附加到请求上下文。

  3. 路由匹配:根据 URL 和请求方法匹配对应接口。

  4. 参数校验:Pydantic 对路径参数、查询参数、请求体进行校验。

  5. 调用业务逻辑:校验成功后进入业务层处理。

  6. 异常处理中心接管:参数异常、业务异常、系统异常、HTTP 异常都进入统一处理。

  7. 构建统一错误响应:转换成标准 JSON 结构。

  8. 记录日志并返回:日志记录 request_id 和错误详情,再把响应返回给客户端。

自定义异常类是给错误贴“类型标签”。比如参数错、业务错、系统错,可以定义成不同异常类型。

app/core/exceptions.py
class AppException(Exception):
def __init__(self, code: str, message: str, detail: dict | None = None):
self.code = code
self.message = message
self.detail = detail or {}
class BusinessException(AppException):
pass
class SystemException(AppException):
pass

业务代码里主动抛出异常,统一处理器负责转换响应。

统一错误处理不是把所有错误都变成一个错误,而是先分类,再统一输出。

类型 典型来源 处理重点
参数校验异常 Pydantic 校验失败、缺字段、类型错误 返回字段级错误,提示前端修正参数
业务异常 用户不存在、用户名重复、余额不足、状态不允许 返回业务错误码和友好提示
系统异常 数据库失败、第三方服务失败、内部逻辑异常 记录详细日志,对外隐藏敏感细节
HTTP 异常 404、401、403、405 等框架或权限错误 保留 HTTP 语义,转换为统一响应
未捕获异常 没有预料到的异常 兜底处理,避免直接暴露堆栈

在项目入口里注册中间件和异常处理器:

app/main.py
from fastapi import FastAPI
from fastapi.exceptions import RequestValidationError
from app.core.exceptions import AppException
from app.core.handlers import (
app_exception_handler,
validation_exception_handler,
unhandled_exception_handler,
)
from app.core.middleware import request_id_middleware
app = FastAPI(title="FastAPI 错误处理示例")
app.middleware("http")(request_id_middleware)
app.add_exception_handler(AppException, app_exception_handler)
app.add_exception_handler(RequestValidationError, validation_exception_handler)
app.add_exception_handler(Exception, unhandled_exception_handler)

实现顺序可以记成:

自定义异常 -> 响应模型 -> 日志配置 -> 全局处理器 -> 业务示例

业务层只负责表达错误语义,不负责拼响应格式。

app/services/user_service.py
from app.core.exceptions import BusinessException
users = {"1": {"id": "1", "username": "kai"}}
def get_user(user_id: str):
user = users.get(user_id)
if not user:
raise BusinessException(
code="USER_NOT_FOUND",
message="用户不存在",
detail={"user_id": user_id},
)
return user

统一处理后,返回给客户端的结构类似:

{
"code": "USER_NOT_FOUND",
"message": "用户不存在",
"detail": {
"user_id": "100"
},
"request_id": "f7b7c7e4-7f1a-4e9b-9d65-2b0e0f7e8c11"
}
prompt.md
## 生成 FastAPI 统一错误处理代码
### 核心目标
报错前端中文可读,后端可定位,日志可追溯。
### 关键要求
1. 自定义业务 / 系统两类异常类;
2. 标准化响应模型,包含 code / message / detail / request_id;
3. 注册全局异常处理器;
4. 在用户信息接口中加入错误处理功能。
### 实现步骤
自定义异常 -> 响应模型 -> 日志配置 -> 全局处理器 -> 业务示例