خطاها و محدودیتها
خطاها و محدودیتها
هر خطا با پوشش بومی پروتکل برمیگردد تا مدیریت خطای SDK شما بدون تغییر کار کند. داتهوش روی پوشش OpenAI چند فیلد اضافه میگذارد که برای تصمیمگیری لازماند.
پوشش خطا
{
"error": {
"type": "invalid_request_error",
"code": "unsupported_parameter",
"message": "…",
"request_id": "…",
"parameter": "anthropic-version",
"retryable": false,
"retry_scope": "never",
"partial_delivery": false
}
}{
"type": "error",
"error": { "type": "invalid_request_error", "message": "…" },
"request_id": "req_…"
}پوشش دوم همان پوشش بومی Anthropic است: کد وضعیت در سرآیند، و دستهٔ خطا در error.type. فیلدهای ریز خطا (code، retryable، retry_scope) فقط در پوشش OpenAI میآیند؛ روی مسیر Anthropic همین اطلاعات را از error.type و کد وضعیت بگیرید.
| فیلد | کاربرد |
|---|---|
| code | روی این شرط بگذارید. ثابت است؛ message قابل بازنویسی است |
| type | دستهٔ خطا (invalid_request_error، authentication_error، rate_limit_error، provider_error و …) |
| message | متن فارسی برای انسان؛ متناسب با مخاطب نوشته شده و قابل بازنویسی است |
| request_id | برای پیگیری پشتیبانی؛ روی مسیر OpenAI در سرآیند X-Request-Id و روی مسیر Anthropic در سرآیند Request-Id هم میآید |
| parameter | نام فیلدی که باعث خطا شده، وقتی مشخص باشد |
| retryable | اینکه تلاش دوباره میتواند موفق شود یا نه |
| retry_scope | یکی از never، same-request-before-first-byte، new-request-after-delay، manual-review |
| retry_after_seconds | وقتی داتهوش میداند چقدر باید صبر کنید |
| partial_delivery | آیا بخشی از پاسخ را گرفتهاید |
message عمداً محافظهکارانه است: نه پرامپت شما، نه پاسخ، نه هویت ارائهدهنده، نه endpoint داخلی و نه اعتبارنامه در آن نیست. اگر پیامی کلی بهنظر میرسد، دلیل همین است؛ روی code و request_id تکیه کنید.
معنای retry_scope
| مقدار | یعنی |
|---|---|
| never | هرگز؛ درخواست مشکل دارد، دوباره فرستادن همان خطا را میدهد |
| same-request-before-first-byte | پیش از نخستین بایت میتوان روی همان مدل دوباره تلاش کرد |
| new-request-after-delay | با تأخیر، بهعنوان یک درخواست تازه |
| manual-review | تلاش دوبارهٔ خودکار جایز نیست؛ باید وضعیت را بررسی کنید |
جدول کدها
«وضعیت» دو عدد دارد: اولی روی /v1/* و دومی روی /anthropic/v1/messages. بعضی کدها بین دو پروتکل وضعیت یکسانی ندارند و همین تفاوت را باید در مدیریت خطا لحاظ کنید.
احراز هویت و دسترسی
| کد | وضعیت OpenAI / Anthropic | retryable | retry_scope | معنا |
|---|---|---|---|---|
| api_key_malformed | 401 / 401 | no | manual-review | ساختار کلید API نامعتبر است |
| api_key_invalid | 401 / 401 | no | manual-review | کلید API معتبر نیست |
| api_key_revoked | 401 / 401 | no | manual-review | کلید API لغو شده است |
| api_key_disabled | 401 / 401 | no | manual-review | کلید API غیرفعال است |
| api_key_expired | 401 / 401 | no | manual-review | کلید API منقضی شده است |
| api_key_model_not_allowed | 403 / 403 | no | manual-review | مدل برای این کلید مجاز نیست |
| api_key_environment_mismatch | 403 / 403 | no | manual-review | محیط کلید با درخواست سازگار نیست |
| api_key_ip_not_allowed | 403 / 403 | no | manual-review | نشانی IP مجاز نیست |
| api_key_scope_insufficient | 403 / 403 | no | manual-review | دسترسی کلید کافی نیست |
| api_key_leak_suspended | 403 / 403 | no | manual-review | کلید مشکوک به افشا تعلیق شد |
| api_key_or_account_spend_limit | 403 / 403 | no | manual-review | سقف هزینهٔ کلید یا حساب رد شد |
| project_or_account_disabled | 403 / 403 | no | manual-review | پروژه یا حساب غیرفعال است |
| api_key_rpm_exceeded | 429 / 429 | yes | new-request-after-delay | سقف درخواست در دقیقه تکمیل است |
| api_key_tpm_exceeded | 429 / 429 | yes | new-request-after-delay | سقف توکن در دقیقه تکمیل است |
| api_key_concurrency_exceeded | 429 / 429 | yes | new-request-after-delay | سقف درخواست همزمان تکمیل است |
مدل، قابلیت و ارائهدهنده
| کد | وضعیت OpenAI / Anthropic | retryable | retry_scope | معنا |
|---|---|---|---|---|
| model_not_found | 404 / 404 | no | never | مدل پیدا نشد |
| model_private_or_admin_only | 404 / 404 | no | never | مدل خصوصی یا ویژهٔ ادمین است |
| model_deprecated_scheduled_or_removed | 410 / 404 | no | never | مدل منسوخ، زمانبندیشده یا حذف شده است |
| model_temporarily_unavailable | 503 / 500 | yes | new-request-after-delay | مدل موقتاً در دسترس نیست |
| unsupported_capability | 400 / 400 | no | never | قابلیت درخواستی پشتیبانی نمیشود |
| unsupported_parameter | 400 / 400 | no | never | پارامتر درخواستی پشتیبانی نمیشود |
| invalid_structured_output_schema | 400 / 400 | no | never | ساختار خروجی معتبر نیست |
| invalid_image_or_media_input | 400 / 400 | no | never | ورودی تصویر یا رسانه معتبر نیست |
| context_length_exceeded | 400 / 400 | no | never | طول زمینه از سقف مدل بیشتر است |
| provider_overloaded | 503 / 529 | yes | new-request-after-delay | ظرفیت ارائهدهنده تکمیل است |
| provider_timeout | 504 / 500 | yes | new-request-after-delay | زمان پاسخ ارائهدهنده پایان یافت |
| provider_auth_or_quota_failure | 503 / 500 | yes | new-request-after-delay | احراز هویت یا سهمیهٔ ارائهدهنده ناموفق است |
| all_same_model_endpoints_unavailable | 503 / 500 | yes | new-request-after-delay | همهٔ مسیرهای همان مدل خارج از دسترساند |
| stream_interrupted_before_first_byte | 502 / 500 | no | manual-review | جریان پیش از نخستین بایت قطع شد |
| partial_stream_after_first_byte | 502 / 500 | no | manual-review | جریان پس از شروع ناقص ماند |
| upstream_usage_missing_or_unknown | 409 / 400 | no | manual-review | مصرف بالادست نامشخص است |
| canonical_mapping_failure | 502 / 500 | no | manual-review | نگاشت مدل داخلی ناموفق بود |
| response_validation_failure | 502 / 500 | no | manual-review | اعتبارسنجی پاسخ ناموفق بود |
کیف پول و صورتحساب
| کد | وضعیت OpenAI / Anthropic | retryable | retry_scope | معنا |
|---|---|---|---|---|
| insufficient_available_balance | 402 / 400 | no | manual-review | موجودی قابلاستفاده کافی نیست |
| reservation_conflict | 409 / 400 | no | manual-review | رزرو مالی با تعارض روبهرو شد |
| price_version_changed_before_start | 409 / 400 | no | manual-review | نسخهٔ قیمت پیش از شروع تغییر کرده است |
| promotional_credit_expired | 402 / 400 | no | manual-review | اعتبار هدیه منقضی شده است |
| spend_limit_daily_monthly_or_total | 403 / 403 | no | manual-review | سقف هزینهٔ روزانه، ماهانه یا کل رد شد |
| reconciliation_required | 409 / 400 | no | manual-review | تطبیق مالی لازم است |
| fx_source_unavailable | 503 / 500 | yes | new-request-after-delay | منبع نرخ ارز در دسترس نیست |
| fx_abnormal_change | 409 / 400 | no | manual-review | تغییر غیرعادی نرخ ارز شناسایی شد |
سرویس و BYOK
| کد | وضعیت OpenAI / Anthropic | retryable | retry_scope | معنا |
|---|---|---|---|---|
| maintenance_mode | 503 / 500 | yes | new-request-after-delay | سامانه در حالت نگهداری است |
| global_incident | 503 / 500 | yes | new-request-after-delay | رخداد سراسری فعال است |
| service_degraded | 503 / 500 | yes | new-request-after-delay | سرویس در وضعیت افت کیفیت است |
| byok_connection_disabled | 403 / 403 | no | manual-review | اتصال BYOK غیرفعال است |
| byok_credential_invalid | 401 / 401 | no | manual-review | اعتبارنامهٔ BYOK معتبر نیست |
| byok_credential_revoked | 401 / 401 | no | manual-review | اعتبارنامهٔ BYOK لغو شده است |
| byok_permission_insufficient | 403 / 403 | no | manual-review | مجوز اتصال BYOK کافی نیست |
| byok_accessible_model_list_empty | 400 / 400 | no | never | فهرست مدلهای BYOK خالی است |
| byok_quota_exhausted | 429 / 429 | yes | new-request-after-delay | سهمیهٔ BYOK تمام شده است |
| byok_provider_unavailable | 503 / 500 | yes | new-request-after-delay | ارائهدهندهٔ BYOK در دسترس نیست |
| byok_fallback_unavailable | 503 / 500 | yes | new-request-after-delay | مسیر جایگزین BYOK در دسترس نیست |
| byok_test_timeout | 504 / 500 | yes | new-request-after-delay | آزمون BYOK به پایان زمان رسید |
| byok_delete_blocked_by_active_route | 409 / 400 | no | manual-review | حذف BYOK بهدلیل مسیر فعال مسدود است |
| byok_secret_decrypt_or_kms_failure | 503 / 500 | yes | new-request-after-delay | رمزگشایی BYOK یا KMS ناموفق بود |
| credential_redemption_denied | 403 / 403 | no | manual-review | بازخرید اعتبارنامه مجاز نشد |
قاعدهٔ تلاش دوباره
فقط وقتی retryable برابر true است دوباره بفرستید و retry_after_seconds را رعایت کنید. از backoff نمایی با jitter استفاده کنید و یک سقف تلاش بگذارید.
هرگز یک خطای غیرقابلتلاشدوباره را در حلقه نگذارید. تکرار insufficient_available_balance یا خطاهای خانوادهٔ api_key_* فقط سهمیهٔ خودتان را میسوزاند.
دو حالت ظریف:
- stream_interrupted_before_first_byte و partial_stream_after_first_byte هر دو manual-review هستند. هیچکدام را خودکار تکرار نکنید؛ در حالت دوم بخشی از پاسخ را گرفتهاید و همان اندازه هم حساب شده است (استریم).
- price_version_changed_before_start و reservation_conflict هم manual-review هستند. داتهوش ترجیح میدهد شما وضعیت را ببینید تا اینکه دو بار روی یک رزرو نامعلوم عمل شود.
محدودیتها و پاسخ 429
سقفها روی هر API key گذاشته میشوند (محدودیتها):
| سقف | کد |
|---|---|
| درخواست در دقیقه | api_key_rpm_exceeded |
| توکن در دقیقه | api_key_tpm_exceeded |
| درخواست همزمان | api_key_concurrency_exceeded |
| هزینه | api_key_or_account_spend_limit |
پاسخهای 429 سرآیند Retry-After را هم برمیگردانند. TPM پیش از اجرا با برآورد بررسی میشود، پس درخواستی با سقف توکن خروجی بزرگ زودتر از آنچه انتظار دارید سهمیهٔ دقیقه را مصرف میکند.
موجودی و صورتحساب
| کد | معنا |
|---|---|
| insufficient_available_balance | موجودی قابلاستفاده برای رزرو این درخواست کافی نیست؛ هیچ مبلغی کم نشده است |
| api_key_or_account_spend_limit | سقف هزینهٔ کلید یا حساب پر شده است |
| reconciliation_required | وضعیت مالی درخواست روشن نیست و به بررسی نیاز دارد |
| reservation_conflict | عملیات همزمان روی همان رزرو؛ بدون بررسی دوباره نفرستید |
«موجودی قابلاستفاده» مبلغی است که در همان لحظه توسط درخواستهای در جریان رزرو نشده است. هر درخواست همزمان تا تسویه یک رزرو نگه میدارد، پس ممکن است موجودی قابلاستفاده کمتر از موجودی کل باشد.
درخواستی که پیش از رسیدن به ارائهدهنده رد شود، هزینهای ندارد. رزرو در همان لحظه آزاد میشود.
گرفتن کمک
request_id را — از بدنهٔ خطا یا سرآیند X-Request-Id / Request-Id — بههمراه زمان رخداد و کدی که گرفتهاید بفرستید. همینها برای ردیابی سرتاسری یک درخواست کافی است. هرگز کلید API خود را نفرستید.