رموز الأخطاء
كل رمز خطأ تعيده واجهة Qirnas API وكيفية التعامل معه
مرجع رموز الأخطاء
كل رمز في الحقل error.code، كما تعيده البوابة على api.mindlabsa.com/v1
| الحالة | الرمز | متى يحدث | ماذا تفعل |
|---|---|---|---|
| 400 | invalid_request | جسم الطلب ليس JSON صالحاً، أو فشل أحد الحقول في التحقق، أو أُرسل حقلان لا يجتمعان. يسمّي param أول حقل مخالف (مثل temperature أو messages.0.role). | أصلح الحقل المذكور في param؛ لا تُعد إرسال الطلب كما هو. |
| 400 | context_length_exceededقد يصل أثناء البث | الرسائل مع ميزانية المخرجات (max_tokens، أو default_max_tokens للنموذج إن لم ترسله) لا تتسع في نافذة سياق النموذج context_window. قيمة param هي messages. | اختصر الرسائل أو خفّض max_tokens؛ وراجع context_window في GET /v1/models. |
| 401 | missing_api_key | لم تُرسل ترويسة Authorization: Bearer <key>. | أرسل مفتاحك في الترويسة Authorization: Bearer <key>. |
| 401 | invalid_api_key | مفتاح API غير معروف أو ملغى أو منتهي الصلاحية. | تأكد من صفحة المفاتيح أن المفتاح ما زال نشطاً، وأنشئ مفتاحاً جديداً إن كان ملغى. |
| 403 | permission_denied | بيانات الاعتماد صحيحة لكنها لا تملك صلاحية هذا الطلب: المسار، أو ترويسة طلب داخلية خاصة بالمنصة، غير متاح لهذا المفتاح. | لا تُعد المحاولة بالمفتاح نفسه. |
| 403 | scope_required | الطلب يحتاج نطاقاً لا يملكه مفتاحك. يسمّي param ما يحتاجه: reasoning (نطاق reasoning)، أو think (نطاق think)، أو model لنموذج يعمل بوضع التفكير المعمّق (نطاق think). أو أن المسار نفسه يحتاج نطاقاً، ولا يُرسل param حينها: POST /v1/embeddings يحتاج embeddings، وPOST /v1/search يحتاج search. | أرسل الطلب دون المعامل (أو بالقيمة false)، أو استخدم مفتاحاً يملك النطاق. المفاتيح التي تُنشأ من هذه البوابة تبدأ دون هذه النطاقات. |
| 403 | model_not_permitted | لا يحق لمفتاحك استخدام هذا النموذج: فهو خارج قائمة النماذج المحددة للمفتاح، أو نموذج من مزوّد خارجي (self_hosted: false) لا يملك المفتاح إذناً به. قيمة param هي model. والمفتاح الذي لا تضم قائمته النموذج الافتراضي يتلقى هذا الرمز أيضاً عند إرسال qirnas أو عدم إرسال model. | اختر نموذجاً من GET /v1/models، فهي تسرد بالضبط النماذج التي يستطيع مفتاحك استدعاءها. لا تُعد المحاولة بالمفتاح نفسه. |
| 404 | not_found | لا يوجد مسار بهذا العنوان، أو أن طريقة HTTP خاطئة. | تحقق من الطريقة والمسار: POST /v1/chat/completions أو GET /v1/models أو POST /v1/embeddings أو POST /v1/search على https://api.mindlabsa.com. |
| 404 | model_not_found | النموذج غير متاح لهذا المفتاح: النموذج الذي لا يحق لمفتاحك رؤيته يعود بالخطأ 404 كأنه غير موجود، ولا تسرده GET /v1/models. (المعرّف الذي لا تعرفه البوابة يخدمه النموذج الافتراضي، مع ترويسة Deprecation.) | اختر نموذجاً من GET /v1/models، أو أرسل qirnas. |
| 413 | request_too_large | جسم الطلب أكبر مما تقبله البوابة: 256 كيلوبايت لـ POST /v1/chat/completions وPOST /v1/embeddings، و100 كيلوبايت لغيرهما. | قلّل حجم الطلب: رسائل أو مدخلات أقل أو أقصر. |
| 429 | rate_limit_exceeded | بلغ مفتاحك حد المعدل في النافذة الحالية. والحد لحسابك: تتشاركه كل مفاتيحك، لكل مسار على حدة، ولـ POST /v1/embeddings وPOST /v1/search حصة إضافية لكل حساب (انظر «حدود المعدل»). | انتظر عدد الثواني في ترويسة Retry-After ثم أعد المحاولة. |
| 429 | upstream_rate_limited | طلب خادم النموذج من البوابة الإبطاء. أثناء البث يصل بدلاً منه upstream_error. | أعد المحاولة بعد قليل بتراجع أسّي. |
| 499 | client_closed_request | انقطع اتصال العميل قبل اكتمال الرد. | لا شيء تعالجه: يُسجَّل فقط، إذ لم يبقَ من يستقبله. |
| 500 | internal_error | خطأ غير متوقع في البوابة. | أعد المحاولة؛ وإن استمر فأرسل إلينا قيمة request_id. |
| 502 | upstream_errorقد يصل أثناء البث | فشل خادم النموذج، أو خدمة البحث أو المتجهات، أو أعاد رداً غير صالح، بما في ذلك بث توقف. | أعد المحاولة بتراجع أسّي. وعلى POST /v1/embeddings يحمل الرد x-should-retry: false: أعد إرساله لاحقاً، أو أصغر، لا فوراً. |
| 503 | model_unavailable | لا يمكن تقديم النموذج: حجبته فحوص البوابة أو أنه غير مهيأ. | إعادة المحاولة لا تفيد حتى يتدخل فريق التشغيل؛ استخدم نموذجاً آخر من GET /v1/models. |
| 503 | model_offline | النموذج موجود لكن وحدة GPU الخاصة به متوقفة (status: offline في GET /v1/models). | استخدم نموذجاً آخر، أو أعد المحاولة لاحقاً. |
| 503 | no_model_available | لم يُحدَّد نموذج (أو أُرسل qirnas أو معرّف غير معروف) والنموذج الافتراضي غير متاح حالياً. | أعد المحاولة لاحقاً. |
| 504 | upstream_timeoutقد يصل أثناء البث | لم يرد النموذج، أو خدمة البحث أو المتجهات، في الوقت المحدد. وفي حالة النموذج يكون السبب غالباً أن تشغيل وحدة GPU من السكون استغرق أطول من مدة الانتظار. | للنموذج: إعادة المحاولة بعد دقيقة تنجح عادةً. وعلى POST /v1/embeddings يحمل الرد x-should-retry: false: أعد إرساله لاحقاً، أو أصغر. |
| 429 | capacity_exceeded | السعة المشتركة للمنصة على POST /v1/embeddings أو POST /v1/search (لكل المستخدمين معاً) مشغولة الآن. وهي ليست حدك أنت (ذاك rate_limit_exceeded). | انتظر عدد الثواني في ترويسة Retry-After ثم أعد المحاولة. |
| 503 | service_unavailable | خدمة البحث أو المتجهات لا تستطيع قبول الطلب الآن: لا يمكن الوصول إليها، أو غير مفعّلة، أو ممتلئة، أو أن مصادرها ترفض الطلبات. | أعد المحاولة بعد عدد الثواني في Retry-After إن أُرسلت، وإلا بتراجع أسّي. ومع x-should-retry: false يطول الانتظار: حاول لاحقاً. |
تُضاف الرموز ولا يُعاد تسميتها أبداً. الحالة 403 تعني أن المفتاح لا يملك صلاحية: scope_required لنطاق ناقص (reasoning أو think أو embeddings أو search)، وmodel_not_permitted لنموذج لا يحق للمفتاح استخدامه، وpermission_denied لمسار غير متاح له. والنموذج الذي لا يحق لمفتاحك رؤيته يعود 404 model_not_found. أخطاء التحقق تعود بـ 400 لا 422. أما 499 فتُسجَّل فقط ولا تصلك.
غلاف الخطأ
شكل JSON الموحّد لكل استجابة خطأ
// 400: a field failed validation, and "param" names it{ "error": { "message": "temperature must not be greater than 2", "type": "invalid_request_error", "code": "invalid_request", "param": "temperature" }, "request_id": "5f0c2a4e-8d7b-4c1e-9a36-2b1f0e7d4c55", // Kept for older clients: read "error" instead "statusCode": 400, "message": ["temperature must not be greater than 2"], "code": "invalid_request"}- •اعتمد على
error.codeفي منطقك، لا علىerror.message: الرسالة موجّهة للبشر وقد تتغير. - •يسمّي
error.paramالحقل المخالف (مثلtemperatureأوmessages.0.role)، أو يكونnull. - •يكرّر
request_idقيمة ترويسةx-request-idفي الرد — أرفقه عند التواصل مع الدعم لنتتبّع الطلب. - •الحقول العلوية
statusCodeوmessageوcodeباقية للعملاء الأقدم فقط؛ اقرأerrorفي أي شيفرة جديدة.
التعامل مع الأخطاء
أعد المحاولة بحسب error.code — والباقي أصلحه
// Retry only what can succeed later; fix the rest. Branch on error.code.const RETRYABLE = new Set([ "rate_limit_exceeded", "upstream_rate_limited", "internal_error", "upstream_error", "model_offline", "no_model_available", "upstream_timeout", "capacity_exceeded", "service_unavailable",]);async function withRetries(call, max = 5) { for (let attempt = 0; ; attempt++) { const res = await call(); if (res.ok) return res; const body = await res.json().catch(() => null); const code = body?.error?.code; // x-should-retry: false (embeddings, search): the work was spent or the wait is long. const noRetry = res.headers.get("x-should-retry") === "false"; if (!RETRYABLE.has(code) || noRetry || attempt >= max) { const id = res.headers.get("x-request-id"); throw new Error(`${code ?? res.status}: ${body?.error?.message} (request ${id})`); } // Honor Retry-After when it is sent; else exponential backoff with jitter. const retryAfter = Number(res.headers.get("retry-after")); const delay = retryAfter > 0 ? retryAfter * 1000 : Math.min(30_000, 2 ** attempt * 1000) + Math.random() * 250; await new Promise((r) => setTimeout(r, delay)); }}أثناء البث: إذا فشل الطلب بعد بدء البث فقد أُرسلت حالة النجاح مسبقاً، فيصلك على الاتصال المفتوح حدث خطأ واحد يحمل كائن error نفسه (مع request_id)، ثم data: [DONE]. لا يحمل هذا الحدث الحقول القديمة statusCode وmessage وcode. تحقق من حقل error في كل حدث قبل قراءة choices. رموزه الممكنة: context_length_exceeded، upstream_error، upstream_timeout.
data: {"error":{"message":"The model could not complete this answer. Please retry.","type":"server_error","code":"upstream_error","param":null},"request_id":"5f0c2a4e-8d7b-4c1e-9a36-2b1f0e7d4c55"}data: [DONE]