Chuyển tới nội dung chính

Error Handling

Scope: Áp dụng chung cho cả Internal API (JWT + X-Team-ID) và External API (X-API-Key).
Trong ngữ cảnh Integration nội bộ, dev nên đọc thêm:

  • Integration (Internal API) — overview domain & error codes theo nghiệp vụ
  • docs/error_codes_design.md — bảng error code chi tiết cho backend/frontend

Format lỗi chuẩn (business error)

{
"code": "BOOKING_NOT_FOUND",
"message": "Booking 123 not found",
"details": {
"booking_id": 123
}
}

Trong đó:

  • code: mã lỗi chuẩn hoá, viết HOA, snake case, ví dụ: BOOKING_NOT_FOUND, TEAM_NOT_ACTIVE.
  • message: thông báo tiếng Anh, rõ ràng, có thể được backend tuỳ biến theo context.
  • details: object chứa thêm thông tin cho client (id, field, constraint, …), có thể rỗng.

Backend định nghĩa toàn bộ mã lỗi tập trung trong app/core/error_codes.py và tài liệu chi tiết tại docs/error_codes_design.md.

HTTP Status Codes

StatusÝ nghĩa
200 OKThành công
201 CreatedTạo mới thành công
400 Bad RequestRequest không hợp lệ
401 UnauthorizedChưa xác thực
403 ForbiddenKhông có quyền
404 Not FoundKhông tìm thấy resource
409 ConflictXung đột dữ liệu (vd: booking overlap)
422 Unprocessable EntityValidation error
429 Too Many RequestsRate limit exceeded
500 Internal Server ErrorLỗi server

Validation Errors (422 - FastAPI validation)

Lỗi validate request từ FastAPI (ví dụ thiếu field, sai kiểu dữ liệu) vẫn dùng format mặc định:

{
"detail": [
{
"loc": ["body", "check_in_date"],
"msg": "field required",
"type": "value_error.missing"
}
]
}

Trong roadmap, các lỗi này có thể được map về format chuẩn với code = "VALIDATION_ERROR", nhưng hiện tại client nên tiếp tục support cả hai dạng:

  • Business error: object có code, message, details.
  • Validation error: danh sách detail như ví dụ trên.

Ví dụ xử lý lỗi

import httpx

response = httpx.post(
"https://api.cohost.vn/api/v1/bookings",
headers={"Authorization": f"Bearer {token}"},
json=payload,
)

data = response.json()

if response.status_code == 409:
# Business error với error code chuẩn hoá
print("Booking conflict:", data.get("code"), "-", data.get("message"))
elif response.status_code == 422 and isinstance(data.get("detail"), list):
# Validation error theo format mặc định của FastAPI
for error in data["detail"]:
print(f"Validation error on {error['loc']}: {error['msg']}")
elif not response.is_success:
response.raise_for_status()