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 OK | Thành công |
201 Created | Tạo mới thành công |
400 Bad Request | Request không hợp lệ |
401 Unauthorized | Chưa xác thực |
403 Forbidden | Không có quyền |
404 Not Found | Không tìm thấy resource |
409 Conflict | Xung đột dữ liệu (vd: booking overlap) |
422 Unprocessable Entity | Validation error |
429 Too Many Requests | Rate limit exceeded |
500 Internal Server Error | Lỗ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
detailnhư 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()