Handling Claude API errors: 429, 529, spend caps and rate limits
TL;DR
Not every error should be retried. A 429 can mean rate limiting (with retry-after) or a spend cap (no retry until next month). Prompt caching raises effective throughput because cache reads don't count toward ITPM on most models.
Ứng dụng gọi Claude API chạy ngon trên máy dev, lên production thì thỉnh thoảng nhận 429, đôi lúc 529, có hôm cả hệ thống "chết" đến đầu tháng sau mà không ai hiểu vì sao. Phần lớn sự cố này đến từ việc đối xử mọi lỗi như nhau: retry tất cả, hoặc không retry gì. Bài này hệ thống hoá các mã lỗi, cơ chế rate limit và cách xử lý đúng theo tài liệu chính thức của Anthropic.
Bảng mã lỗi: cái nào retry, cái nào không
| HTTP | error.type | Nguyên nhân | Retry? |
|---|---|---|---|
| 400 | invalid_request_error | Request sai format/nội dung; cũng dùng khi chạm spend limit do bạn tự đặt | Không, sửa request |
| 401 | authentication_error | API key sai, bị thu hồi, hết hạn | Không |
| 402 | billing_error | Vấn đề thanh toán | Không |
| 403 | permission_error | Key không có quyền với tài nguyên | Không |
| 404 | not_found_error | Sai endpoint hoặc ID | Không |
| 413 | request_too_large | Vượt kích thước (Messages 32 MB, Batch 256 MB, Files 500 MB) | Không, cắt nhỏ |
| 429 | rate_limit_error | Vượt rate limit, hoặc chạm spend cap của tier | Có, theo retry-after (trừ spend cap) |
| 500 | api_error | Lỗi nội bộ | Có, exponential backoff |
| 504 | timeout_error | Xử lý quá lâu | Có; nên chuyển sang streaming |
| 529 | overloaded_error | API quá tải chung, không phải lỗi của riêng bạn | Có, backoff |
Lỗi luôn trả về JSON có error.type, error.message và request_id. Mỗi response cũng có header request-id: luôn log giá trị này, đó là thứ đầu tiên support hỏi.
Rate limit hoạt động thế nào?
- Ba loại limit theo model: RPM (request/phút), ITPM (input token/phút), OTPM (output token/phút). Vượt bất kỳ cái nào đều nhận 429.
- Token bucket: dung lượng được nạp lại liên tục chứ không reset theo phút tròn. 60 RPM có thể được áp như 1 request/giây, nên burst ngắn vẫn dính 429 dù tổng trong phút chưa vượt.
- Theo tier: tổ chức được xếp tier tự động theo lịch sử dùng. Tổ chức mới có thể bắt đầu ở tier Evaluation với limit thấp hơn.
- Acceleration limit: tăng traffic đột ngột có thể nhận 429 dù chưa chạm limit danh nghĩa. Hãy tăng tải từ từ.
Prompt caching = tăng limit miễn phí
Với hầu hết model, cache_read_input_tokens không tính vào ITPM; chỉ input_tokens và cache_creation_input_tokens bị tính. Tài liệu đưa ví dụ: limit 2 triệu ITPM, tỉ lệ cache hit 80% thì xử lý được hiệu quả khoảng 10 triệu input token/phút. Còn OTPM chỉ đếm token thực sinh ra, max_tokens đặt cao không làm hao limit.
Bẫy lớn: 429 vì chạm spend cap
Mỗi tier có trần chi tiêu tháng. Khi chạm, API trả 429 cùng error.type với rate limit, nhưng:
- Không có header
retry-after, vàerror.details.error_codelàenforced_spend_limit_reached. - Retry vô ích cho đến 00:00 UTC ngày 1 tháng sau, trừ khi nâng tier.
Nếu code chỉ nhìn status 429 rồi retry vô hạn, bạn sẽ đốt CPU và log trong khi người dùng chờ mãi. Phân biệt bằng error_code và báo động ngay.
Logic xử lý gợi ý
try:
resp = client.messages.create(...)
except anthropic.RateLimitError as e:
body = e.body or {}
code = body.get("error", {}).get("details", {}).get("error_code")
if code == "enforced_spend_limit_reached":
alert_oncall("Chạm spend cap"); raise # không retry
raise # để SDK/hàng đợi retry
except (anthropic.APIStatusError) as e:
log.error("claude_error", status=e.status_code,
request_id=e.response.headers.get("request-id"))
raise
SDK chính thức đã tự retry 2 lần với exponential backoff cho lỗi kết nối, 429 và 5xx, có tôn trọng retry-after. Chỉnh bằng max_retries. Đừng bọc thêm vòng retry thủ công bên ngoài mà không giới hạn, kẻo nhân số lần thử lên nhiều lần.
Theo dõi bằng header
Mỗi response có anthropic-ratelimit-requests-remaining, anthropic-ratelimit-input-tokens-remaining, anthropic-ratelimit-output-tokens-remaining và các header -reset (định dạng RFC 3339). Ghi chúng vào metrics để thấy trước khi nào sắp chạm trần.
Áp dụng thế nào?
- Dev: Bắt lỗi theo class của SDK, không so chuỗi message. Log
request-id. Dùng streaming cho request dài thay vì tăng timeout. - Tech Lead: Đưa job khối lượng lớn qua hàng đợi có giới hạn đồng thời; job không gấp chuyển sang Batch API. Bật prompt caching cho system prompt và tài liệu lặp lại để tăng throughput.
- PM: Đặt spend limit cho từng workspace trong Console và cảnh báo trước 80% để không bị "tắt" giữa tháng.
Sources & references
- Claude API errors — Claude Docs
- Rate limits — Claude Docs