> ## Documentation Index
> Fetch the complete documentation index at: https://docs.madiad.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Lỗi

> Mọi lỗi MADIAD Hub trả về đều dùng chung một cấu trúc, đây là bảng tham chiếu đầy đủ.

Mọi request thất bại đều trả về cùng một cấu trúc JSON, bất kể endpoint nào hay lỗi gì:

```json theme={null}
{
  "error": {
    "code": "invalid_request",
    "message": "`platforms` is required (array or comma-separated)."
  }
}
```

`code` là một chuỗi ổn định, có thể đọc bằng máy, bạn có thể dùng nó để rẽ nhánh xử lý. `message` là mô tả dễ đọc cho người, hữu ích khi ghi log, nhưng đừng parse nó vì nội dung có thể thay đổi theo thời gian.

Khi nền tảng đích từ chối một bài đăng, `message` mở đầu bằng **nguyên văn của nền tảng đó**, thường là tiếng Anh. Nếu MADIAD Hub có bản dịch tiếng Việt cho câu đó, bản dịch nằm ngay sau `· Tạm dịch:`. Đây là bản dịch đúng nghĩa: nó giữ đủ các mệnh đề và các con số của nền tảng, không thêm lời khuyên nào của chúng tôi. Câu nào chưa có bản dịch thì giữ nguyên tiếng Anh chứ không đoán bừa. Phần duy nhất bị sửa còn lại là những gì thuộc về chúng tôi: tên, địa chỉ hỗ trợ và link tài liệu của backend xuất bản được đổi thành của MADIAD, còn định danh Profile nội bộ thì được gỡ bỏ.

## Bảng mã lỗi

| `code`                    | HTTP status        | Xảy ra khi nào                                                                                                                                                                                                                                                             | Cách xử lý                                                                                                                                                                                                                                                                           |
| ------------------------- | ------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `unauthorized`            | 401                | API key thiếu, sai định dạng hoặc không hợp lệ (hoặc session dashboard đã hết hạn trên các route dùng browser session).                                                                                                                                                    | Kiểm tra header `Authorization: Bearer`. Cấp lại hoặc xoay vòng key từ dashboard. Không nên retry khi chưa sửa thông tin xác thực.                                                                                                                                                   |
| `forbidden`               | 403                | Tài khoản hợp lệ nhưng không được phép thực hiện hành động này, ví dụ tài khoản đang ở trạng thái `expired` hoặc `banned`, hoặc một tính năng (như tự động hoá DM/engagement) không nằm trong gói hiện tại.                                                                | Không retry nguyên trạng. Kiểm tra trạng thái tài khoản hoặc nâng cấp gói.                                                                                                                                                                                                           |
| `not_found`               | 404                | Route không tồn tại, hoặc một resource được tham chiếu (Profile...) không thuộc về tài khoản của bạn.                                                                                                                                                                      | Kiểm tra lại URL và các ID. Không retry được nếu không đổi request.                                                                                                                                                                                                                  |
| `invalid_request`         | 400                | Request không hợp lệ, có thể do phía Hub hoặc do chính nền tảng đích từ chối: thiếu field bắt buộc, caption hoặc title vượt giới hạn ký tự của nền tảng, liệt kê nền tảng không hỗ trợ, URL không phải link `https://` hợp lệ, nền tảng từ chối nội dung.                  | Sửa request theo `message`. Không retry được nếu không đổi payload.                                                                                                                                                                                                                  |
| `quota_exceeded`          | 429                | Một hạn mức đã dùng hết: phút xử lý FFmpeg hằng tháng hoặc số DM theo ngày. Đăng bài không còn hạn mức tháng trên gói trả phí, nên với một lệnh đăng thì lỗi này chỉ có nghĩa là tài khoản **chưa có gói đang hoạt động**.                                                 | Không retry được cho tới khi hạn mức reset hoặc gói được kích hoạt/nâng cấp. Kiểm tra [Mức sử dụng](/vi/concepts/usage) và hiển thị thông báo cho người dùng thay vì lặp lại retry.                                                                                                  |
| `no_active_plan`          | 403                | Bạn đang cố kết nối một tài khoản mạng xã hội (tạo connect link) nhưng tài khoản chưa có gói đang hoạt động (hạn mức Profile bằng 0).                                                                                                                                      | Kích hoạt gói dịch vụ từ trang thanh toán của dashboard trước. Không retry nguyên trạng.                                                                                                                                                                                             |
| `profile_limit_reached`   | 403                | Tạo thêm Profile mới sẽ vượt giới hạn Profile của gói hiện tại.                                                                                                                                                                                                            | Nâng cấp gói hoặc xoá bớt một Profile không dùng đến, rồi thử lại.                                                                                                                                                                                                                   |
| `rate_limited`            | 429                | Bạn đã vượt giới hạn số request mỗi phút (tách biệt với các hạn mức sử dụng, xem [Rate limit](/vi/concepts/rate-limits)), **hoặc** backend xuất bản chặn tốc độ lời gọi.                                                                                                   | Giảm tốc độ gửi và tuân theo header `Retry-After` (tính bằng giây) trước khi thử lại.                                                                                                                                                                                                |
| `idempotency_conflict`    | 409                | `Idempotency-Key` bạn gửi đã được dùng cho một request với tham số **khác**.                                                                                                                                                                                               | Dùng key mới cho request thực sự mới, hoặc kiểm tra lại payload có khớp với lần gửi đầu tiên không. Không nên retry an toàn với cùng key nhưng khác body.                                                                                                                            |
| `idempotency_in_progress` | 409                | Một request với `Idempotency-Key` này vẫn đang được xử lý (một lần retry đồng thời hoặc chồng lấn xảy ra khi lần thử đầu chưa xong).                                                                                                                                       | Đợi một chút rồi thử lại cùng request với cùng key, nó sẽ nhận kết quả đã lưu ngay khi lần thử đầu hoàn tất.                                                                                                                                                                         |
| `platform_not_startable`  | 400                | Nền tảng có hỗ trợ đăng bài nhưng không khởi tạo được từ endpoint kết nối theo từng nền tảng (Bluesky dùng app password chứ không phải OAuth).                                                                                                                             | Dùng liên kết kết nối chung từ [`POST /v1/connections/start`](/vi/concepts/profiles) cho nền tảng này.                                                                                                                                                                               |
| `link_not_found`          | 404                | Token của liên kết kết nối không tồn tại hoặc đã hết hạn (liên kết sống 48 giờ). Một mã dùng chung cho cả hai trường hợp, để không ai dò được token nào có thật.                                                                                                           | Tạo liên kết mới bằng `POST /v1/connections/start`.                                                                                                                                                                                                                                  |
| `platform_not_connected`  | 409                | Profile chưa kết nối tài khoản cho một nền tảng có trong request, nên bài không thể đăng như đã gửi.                                                                                                                                                                       | Kết nối tài khoản trong mục **Kết nối** của dashboard, hoặc bỏ nền tảng đó khỏi `platforms`. Gửi lại y nguyên request thì không thể thành công. Nếu cứ sau mỗi bài đăng được là lại gặp lỗi này, nền tảng đang hạn chế tài khoản và kết nối lại sẽ không gỡ được, hãy đọc `message`. |
| `upstream_error`          | 502                | Backend xuất bản thực sự gặp sự cố: lỗi mạng, hoặc backend trả 5xx. Vấn đề về nội dung và quyền **không** nằm ở đây, chúng trả `400` hoặc `409`.                                                                                                                           | Lỗi tạm thời. An toàn để retry toàn bộ request **chỉ khi** bạn đã gửi `Idempotency-Key` để lần retry không tạo bài đăng trùng.                                                                                                                                                       |
| `upstream_timeout`        | 502                | Việc đăng bài vượt quá thời gian MADIAD Hub chờ, nên **chưa xác định được kết quả**: bài có thể đã lên. Lượt đăng không được hoàn, và `Idempotency-Key` bạn gửi đã được chốt vào câu trả lời này, nên gửi lại cùng key sẽ nhận đúng kết quả này chứ không tạo bài thứ hai. | **Đừng** retry ngay. Hãy kiểm tra lịch sử đăng hoặc kiểm tra trực tiếp trên nền tảng trước; nếu quyết định gửi lại thì dùng một `Idempotency-Key` MỚI.                                                                                                                               |
| `internal_error`          | 500 (hiếm khi 502) | Lỗi chưa được xử lý bên trong MADIAD Hub (lỗi database, exception ngoài dự kiến). Hiếm gặp và không phải do bạn gây ra. Một vài thao tác có thể trả về 502 thay vì 500.                                                                                                    | Coi cả hai là retryable: thử lại với backoff. Nếu vẫn lặp lại, liên hệ hỗ trợ kèm chi tiết request.                                                                                                                                                                                  |

<Tip>
  Xem [Idempotency](/vi/concepts/idempotency) để hiểu `Idempotency-Key` ngăn tạo bài đăng trùng lặp khi retry như thế nào, và [Rate limit](/vi/concepts/rate-limits) để hiểu giới hạn theo phút đứng sau `rate_limited`.
</Tip>

## Khi nào nên retry?

Hãy phân nhánh theo **mã trạng thái**, đừng bao giờ dựa vào câu chữ trong `message`:

| Trạng thái | Ý nghĩa                                                        | Retry y nguyên request?                                                                                                                                                          |
| ---------- | -------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `4xx`      | Vấn đề nằm ở request, ở nội dung, hoặc ở trạng thái tài khoản. | **Không.** Phải sửa gì đó trước, gửi lại y nguyên sẽ hỏng y như cũ.                                                                                                              |
| `429`      | Gửi quá nhanh, hoặc đã hết hạn mức.                            | Có, sau khoảng thời gian ghi trong `Retry-After`.                                                                                                                                |
| `5xx`      | Lỗi phía Hub hoặc phía backend xuất bản.                       | Có, kèm backoff, và nhớ gửi `Idempotency-Key` để lần retry không tạo bài trùng. Ngoại lệ duy nhất là `upstream_timeout`: kết quả chưa xác định, phải kiểm tra trước khi gửi lại. |

<Warning>
  Tới trước ngày 07/08/2026, mọi lỗi phát sinh từ backend xuất bản đều được báo là `502`, kể cả những lỗi vĩnh viễn như caption vượt giới hạn hoặc Profile chưa kết nối tài khoản. Vì vậy các automation retry theo `5xx` đã retry cả những request không bao giờ thành công được. Nếu tích hợp của bạn đang lách chỗ này bằng cách đọc `message`, giờ có thể bỏ đoạn đó và phân nhánh theo mã trạng thái.
</Warning>

## Lỗi không có envelope chuẩn

Một request multipart quá lớn có thể bị chặn ở tầng biên mạng **trước khi** tới được MADIAD Hub, phản hồi khi đó là `413 Request Entity Too Large` dạng thuần (không có envelope JSON). Hãy chuyển sang gửi ảnh bằng [`photo_urls[]`](/vi/concepts/posts#đăng-ảnh-bằng-url): MADIAD Hub sẽ tự tải ảnh về phía máy chủ, nên request body luôn nhỏ gọn bất kể ảnh lớn đến đâu. Nén file ảnh lại cũng là một cách nếu chỉ vượt nhẹ.
