خطاها
هر کد خطای API دانا، علتش و کاری که باید بکنید، با نمونه پاکت خطا
هر خطا یک پاسخ JSON با کد HTTP درست است. دو رابط دانا دو شکل پاکت جدا دارند: مسیرهای /v1/messages پاکت Anthropic میگیرند و بقیه مسیرها پاکت OpenAI.
جدول تشخیص سریع
| کد | چه اتفاقی افتاده | کار بعدی |
|---|---|---|
400 | بدنه درخواست ناقص یا نامعتبر است | پیام خطا فیلد مقصر را میگوید؛ همان را درست کنید |
401 | کلید نیست یا شناخته نشد | هدر Authorization: Bearer ... را بررسی کنید |
402 | اعتبار مسیر بالادست تمام شده | تلاش مجدد بیفایده است؛ با پشتیبانی تماس بگیرید |
403 | کلید معتبر است ولی این مسیر را ندارد | مسیرهای internal فقط برای سرویسهای داخلی دانا هستند |
404 | مسیر یا منبع وجود ندارد | آدرس و شناسه مدل را بازبینی کنید |
413 | بدنه درخواست از سقف بزرگتر است | پیامها را کوتاه یا تکهتکه کنید |
429 | نرخ درخواست، ظرفیت، سقف توکن یا اعتبار | به بخش ۴۲۹ بروید؛ چهار حالت جداگانه دارد |
500 | خطای پیشبینینشده در گیتوی | با backoff تا سه بار تلاش مجدد کنید |
502 | گیتوی به موتور مدل نرسید | تلاش مجدد کنید؛ اگر ادامه داشت گزارش بدهید |
503 | سرویسدهی مدل هنوز روشن نشده | تلاش مجدد نکنید؛ code را بخوانید |
504 | موتور مدل بهموقع جواب نداد | درخواست را کوچکتر کنید و دوباره بفرستید |
شکل پاکت خطا
رابط OpenAI (/v1/chat/completions، /v1/models و بقیه):
{
"error": {
"message": "Invalid API key.",
"type": "authentication_error",
"param": null,
"code": null
}
}param همیشه null است. فیلد code فقط در چند خطای مشخص مقدار میگیرد و در بقیه null میماند.
رابط Anthropic (/v1/messages و /v1/messages/count_tokens):
{
"type": "error",
"error": {
"type": "authentication_error",
"message": "Invalid API key."
}
}دقت کنید که پاکت Anthropic یک type: "error" در سطح بیرونی هم دارد. SDK رسمی Anthropic روی همین فیلد حساب میکند.
مقدار type بر اساس کد
| کد | رابط OpenAI | رابط Anthropic |
|---|---|---|
400 | invalid_request_error | invalid_request_error |
401 | authentication_error | authentication_error |
403 | permission_error | permission_error |
404 | not_found_error | not_found_error |
409 | conflict_error | api_error |
413 | invalid_request_error | request_too_large |
429 | rate_limit_error | rate_limit_error |
| بقیه | api_error | api_error |
خطاها به تفکیک کد
400 - درخواست نامعتبر
پیام خطا دقیقا میگوید کجا ایراد دارد. رایجترینها:
{"error": {"message": "Request body must include a 'messages' array.", "type": "invalid_request_error", "param": null, "code": null}}| پیام | علت | راهحل |
|---|---|---|
Request body must include a 'messages' array. | بدنه JSON نیست یا messages ندارد | ساختار بدنه را با Chat Completions بسنجید |
Request body must be a JSON object. | بدنه count_tokens آبجکت نیست | یک آبجکت JSON بفرستید |
Invalid X-Dana-Harness value ... | مقدار هدر harness اشتباه است | یکی از سه مقدار none یا base یا agent |
Invalid effort ... | سطح effort ناشناخته است | چهار سطح مجاز low و medium و high و max |
خطاهای اعتبارسنجی خودکار (نوع اشتباه یک پارامتر، مثلا temperature رشتهای) هم همین 400 را میگیرند و متن خطا فهرست فیلدهای مقصر را برمیگرداند.
401 - احراز هویت ناموفق
{"error": {"message": "Missing API key.", "type": "authentication_error", "param": null, "code": null}}چهار حالت جدا با چهار پیام جدا:
Missing API key.هدرAuthorizationارسال نشده.Invalid API key.کلید در پایگاه داده پیدا نشد؛ شاید غیرفعال شده یا حرفی جا افتاده.internal_app key requires X-Dana-User-Id and X-Dana-Session-Id.مربوط به کلیدهای داخلی است.X-Dana-User-Id is only valid with an internal_app key.این هدر را از درخواست بردارید.
اگر کلید تازه ساختهاید و همچنان 401 میگیرید، فاصله یا خط جدید اضافه در متغیر محیطی را بررسی کنید. شرح کامل را در احراز هویت بخوانید.
402 - اعتبار بالادست تمام شده
{"error": {"message": "Router credit/quota exhausted.", "type": "insufficient_quota", "param": null, "code": "router_credit_exhausted"}}این خطا به حساب شما ربط ندارد؛ مربوط به مسیر بالادست دانا است. تلاش مجدد جوابش را عوض نمیکند.
403 - دسترسی ممنوع
کلید درست است اما اجازه این مسیر را ندارد. مسیرهای /internal/... فقط با کلید internal_app باز میشوند و برای مصرفکننده عمومی API در دسترس نیستند.
413 - بدنه بیش از حد بزرگ
گیتوی پیش از خواندن بدنه، Content-Length را با سقف پیکربندیشده میسنجد و درخواست را همانجا رد میکند.
{"error": {"message": "Request body too large.", "type": "invalid_request_error", "param": null, "code": null}}تاریخچه مکالمه را کوتاه کنید یا متنهای بلند را تکهتکه بفرستید.
کد 429 - چهار حالت جدا
429 چهار علت متفاوت دارد. اول type را بخوانید، بعد تصمیم بگیرید.
۱. عبور از نرخ درخواست کلید - type: "rate_limit_error"
{"error": {"message": "Rate limit exceeded.", "type": "rate_limit_error", "param": null, "code": null}}این پاسخ چهار هدر هم دارد:
Retry-AfterX-RateLimit-LimitX-RateLimit-RemainingX-RateLimit-Reset
به جای عدد ثابت، به Retry-After گوش بدهید. جزئیات را در محدودیتها ببینید.
۲. اتمام اعتبار - type: "insufficient_quota"
{"error": {"message": "You have insufficient credit. Please top up your balance.", "type": "insufficient_quota", "param": null, "code": "insufficient_quota"}}تلاش مجدد کمکی نمیکند. از بخش اعتبار کنسول شارژ کنید.
۳. رسیدن به سقف پنجره توکن - type: "window_cap"
این حالت پاکت مخصوص خودش را دارد و روی رابط OpenAI عینا برگردانده میشود:
{
"error": {
"type": "window_cap",
"which": "session_4h",
"reset_at": "<ISO 8601 timestamp>",
"upgrade_url": "https://console.dana.expert/plans"
}
}| فیلد | معنا |
|---|---|
which | کدام پنجره پر شده: session_4h یا weekly |
reset_at | لحظه دقیق باز شدن پنجره، به وقت UTC |
upgrade_url | نشانی ارتقای پلن در کنسول |
تا رسیدن reset_at صبر کنید؛ تلاش زودتر همین جواب را میگیرد. روی رابط Anthropic همین خطا با پاکت استاندارد Anthropic و نوع rate_limit_error برمیگردد.
۴. پرشدن ظرفیت لحظهای - type: "capacity_busy"
فیلد eta_seconds تخمین زمان خالی شدن صف را میدهد؛ این یکی ارزش تلاش مجدد دارد.
500 - خطای داخلی
{"error": {"message": "Internal server error.", "type": "api_error", "param": null, "code": null}}پاسخ عمدا جزئیات ندارد. x-request-id را از هدر پاسخ بردارید و همان را به پشتیبانی بدهید؛ لاگ سمت ما با همین شناسه پیدا میشود.
502 و 504 - مشکل موتور مدل
| کد | پیام | type | معنا |
|---|---|---|---|
502 | Cannot reach the model backend. | api_error | گیتوی نتوانست به موتور وصل شود |
504 | Upstream model timed out. | timeout_error | موتور در مهلت مقرر جواب نداد |
هر دو گذرا هستند. روی 504 علاوه بر تلاش مجدد، max_tokens را کمتر کنید.
503 - سرویسدهی مدل روشن نیست
{"error": {"message": "Dana model serving is coming soon.", "type": "api_error", "param": null, "code": "coming_soon"}}روی رابط Anthropic:
{"type": "error", "error": {"type": "api_error", "message": "Dana model serving is coming soon."}}در این حالت چهار مسیر مدل بستهاند:
/v1/chat/completions/v1/completions/v1/messages/v1/models
بقیه سرویس سر جایش است: ساخت کلید، شارژ اعتبار و گزارش مصرف کار میکنند. تلاش مجدد روی این خطا بیفایده است.
سیاست تلاش مجدد
import random
import time
import httpx
RETRYABLE = {429, 500, 502, 503, 504}
def call(payload, api_key, max_attempts=3):
for attempt in range(max_attempts):
response = httpx.post(
"https://api.dana.expert/v1/chat/completions",
headers={"Authorization": f"Bearer {api_key}"},
json=payload,
timeout=120,
)
if response.status_code not in RETRYABLE:
response.raise_for_status()
return response.json()
body = response.json().get("error", {})
# این حالتها با تلاش مجدد درست نمیشوند.
if body.get("type") == "window_cap" or body.get("code") in (
"coming_soon",
"insufficient_quota",
):
raise RuntimeError(body.get("message"))
wait = float(response.headers.get("Retry-After", 2**attempt))
time.sleep(wait + random.random())
raise RuntimeError("سه تلاش پیاپی ناموفق بود")قاعدههای پشت این کد:
- روی
429باtype: "rate_limit_error"یاcapacity_busyتلاش مجدد کنید، با backoff نمایی و کمی jitter. - روی
429باwindow_capیاinsufficient_quotaتلاش مجدد نکنید؛ اولی زمان مشخص دارد، دومی شارژ میخواهد. - روی
503باcodeبرابرcoming_soonصبر کنید تا اعلام راهاندازی. 4xxغیر از429را در کد خودتان مدیریت کنید. همان درخواست، همان جواب.x-request-idهر پاسخ را لاگ کنید. بدون آن، پیگیری یک خطای تکباره تقریبا ناممکن است.
صفحههای مرتبط
- شروع سریع - نخستین درخواست موفق
- احراز هویت - ریشه بیشتر خطاهای
401و403 - محدودیتها - جزئیات
429و هدرهای نرخ - قیمت و توکن - اعتبار و شمارش توکن