Skip to content

建立 2026-09-14 更新 2026-09-14

錯誤處理

驗證失敗時 FastAPI 已經會回 422。業務上的失敗——找不到資源、沒權限、衝突——要你自己用 HTTPException 丟出,客戶端才能依狀態碼處理,而不是從 200 的 JSON 裡猜。

HTTPException 表達可預期錯誤

from fastapi import FastAPI, HTTPException

app = FastAPI()

fake_db = {"1": {"name": "筆記本"}}


@app.get("/items/{item_id}")
def read_item(item_id: str):
    item = fake_db.get(item_id)
    if item is None:
        raise HTTPException(status_code=404, detail="找不到這個商品")
    return item

raise 之後函式結束,框架把 detail 序列化成 JSON:{"detail": "找不到這個商品"}。可加上 headers,例如認證失敗時回 WWW-Authenticate

常用狀態碼:

狀態碼 何時使用
400 請求語法對,但業務規則不接受
401 未提供或無效的認證
403 已認證,但沒有權限
404 資源不存在
409 與現有資料衝突(例如帳號已註冊)
422 驗證失敗(框架自動處理居多)

detail 可以是字串,也可以是結構化資料(list / dict),方便前端對欄位顯示錯誤。

不要用例外處理「正常流程」以外的事

HTTPException呼叫端預期得到的失敗。程式自己炸了(資料庫斷線、未捕捉的 bug)應回 500,並靠日誌排查;不要把內部 stack 傳給客戶端。

若要統一包裝某種錯誤,可用例外處理器:

from fastapi import Request
from fastapi.responses import JSONResponse


class UnicornException(Exception):
    def __init__(self, name: str):
        self.name = name


@app.exception_handler(UnicornException)
async def unicorn_handler(request: Request, exc: UnicornException):
    return JSONResponse(
        status_code=418,
        content={"message": f"{exc.name} 現在忙線中"},
    )

入門階段不必急著自訂全域格式;先把每個端點的 404 / 401 / 403 丟對,文件與客戶端就已經好用很多。

進一步學習