الأخطاء والحدود
رموز أخطاء GetVibe API: 401 (المفتاح)، 402 (الرصيد)، 403 (IP)، 429 (حد المعدل). كيفية التعامل مع الأخطاء وإعادة المحاولة بتراجع أُسّي.
الأخطاء التي ينتجها GetVibe على /v1/* لها غلاف JSON يحتوي على error.message وerror.type وerror.code. لا تعتمد على نص الرسالة أو ترويسات خدمات الطرف الثالث كعقد.
تنسيق الخطأ
{
"error": {
"message": "insufficient balance",
"type": "insufficient_quota",
"code": 402,
"request_id": "8d4b6b3a-..."
}
}رموز الاستجابة
| المعلمة | النوع | الوصف |
|---|---|---|
401 | authentication_error / 401 | مفتاح مفقود أو غير صالح التنسيق، أو المفتاح معطّل. لا تُعِد المحاولة حتى يتم تصحيح بيانات الاعتماد. |
402 | insufficient_quota / 402 | لا يوجد رصيد أو حد متاح — الانتظار لا يحل المشكلة. لا يحمل الرمز 402 أبدًا ترويسة Retry-After ولا ينبغي إعادة المحاولة: اشحن الرصيد، أو انتظر حتى تُعاد دورة نافذة الاشتراك. |
403 | permission_error or policy type / 403 | عنوان IP أو النموذج أو السياسة لا يسمح بالطلب. لا تُعد المحاولة دون تغيير الطلب أو الإعدادات. |
429 | rate_limit_exceeded, inflight_client_cap or rate_limit_error / 429 | حدّ معدّلك، أو حدّ تزامنك، أو حجز رصيد يمسكه طلب متزامن لك لفترة وجيزة (السبب reserved_in_flight)، أو حدّ مورّد. أعد المحاولة فقط بعد Retry-After؛ ولا يعني 429 أبدًا أن رصيدك استُهلك بالكامل. |
410 | media_endpoint_retired / media_endpoint_retired | فقط /v1/images/edits و/v1/video/generations و/v1/videos (متوقفة). لا تُعد المحاولة؛ انتقل إلى /api/media/generate. ويُخدَم /v1/images/generations. |
413 | invalid_request_error / 413 | Files API فقط: حجم الملف يتجاوز 50 MiB. قلّل حجم الملف، ثم أنشئ طلباً جديداً. |
503 | overloaded / 503 | حِمل زائد على الحافة العالمية. أعد المحاولة بعد Retry-After: 2. قد لا تكون أخطاء 503 الأخرى قابلة لإعادة المحاولة دون تغيير النموذج أو الطلب. |
أخطاء الطلبات (400, 413, 422): الرموز والحلول
يتضمن كل خطأ في الطلب رمز error.code ثابتًا من الجدول أدناه، وerror.param يحدد الحقل المعني (وتكون قيمته null عندما لا يحدد النموذج حقلًا)، ورابطًا إلى الصف المطابق في نهاية error.message — إذ لا يعرض Codex وغيره من أدوات CLI سوى الرسالة، لذا يُدرج الرابط فيها.
| error.code | error.param | ما ينبغي فعله |
|---|---|---|
unsupported_parameter | اسم الحقل | لا يقبل النموذج أو القناة المحددة هذه المعلمة. أزِلها من الطلب (في Codex/بيئات التطوير المتكاملة، من الإعدادات) وأعد المحاولة. |
invalid_parameter_value | اسم الحقل | المعلمة موجودة، لكن قيمتها غير مسموح بها لهذا النموذج: مثل أن تكون temperature بقيمة غير 1 عند تفعيل الاستدلال، أو أن تتجاوز max_tokens الحد الأقصى، أو أن تكون effort بالقيمة "none" عندما لا يمكن إيقاف الاستدلال. صحّح القيمة وفقًا لما توضحه الرسالة. |
missing_parameter | اسم الحقل | أحد الحقول المطلوبة مفقود أو فارغ. أضِفه. |
invalid_tool_schema | tools[].function.* | رُفض تعريف أداة: لا يجوز أن تتضمن الأسماء سوى أحرف لاتينية وأرقام و"_" و"-"؛ ويجب أن تكون المعلمات وفق JSON Schema يكون نوع جذرها type: "object". أو اختر صيغة أخرى من النموذج. |
tool_choice_unsupported | tool_choice | لا يدعم النموذج فرض اختيار أداة. أرسل tool_choice بالقيمة "auto" أو "none". |
invalid_tool_history | messages / input | يتضمن السجل استدعاء أداة بلا نتيجة. أضِف النتيجة باستخدام id نفسه، أو احذف الاستدعاء مع نتيجته عند تقليص السجل. |
invalid_image | — | تعذرت قراءة الصورة. أرسل ملفًا كاملًا بصيغة PNG أو JPEG أو WebP أو GIF (لا تُقبل صيغ BMP وTIFF وAVIF وSVG). |
unsupported_input_modality | — | لا يقبل النموذج هذا النوع من المرفقات (PDF أو صوت أو فيديو أو صور). أزِله أو اختر نموذجًا يذكر إدخاله في الكتالوج أنه يقبل هذا النوع من المدخلات. |
conversation_state_unreadable | — | أُنشئ الاستدلال الموجود في السجل بواسطة قناة أخرى. الطلب صالح؛ أعد المحاولة، وإذا تكرر الخطأ، فابدأ محادثة جديدة. |
invalid_json | — | نص الطلب ليس بتنسيق JSON أو وصل مبتورًا. للمحادثات الطويلة جدًا التي تتضمن صورًا، ابدأ محادثة جديدة أو اضغط السجل. |
request_too_large | — | حجم الطلب كبير جدًا. قلّل المرفقات أو السجل. |
request_rejected_by_channel | — | رفضت قناة النموذج الطلب دون تحديد سبب؛ وعلى الأرجح أن الطلب نفسه صالح. أعد المحاولة؛ وإذا تكرر الرفض، فاختر صيغة أخرى من النموذج (اللاحقة بعد النقطتين الرأسيتين) أو النموذج دون لاحقة. إذا لم يُجدِ ذلك، فتواصل مع الدعم وأرفق request_id. |
model_not_available_on_route | — | المسار غير مُعدّ لهذا النموذج. اختر نموذجًا آخر أو صيغة أخرى. |
context_length_exceeded | messages / input / prompt | يتجاوز الطلب سعة نافذة السياق. اضغط السجل (في Codex: /compact) أو اختر نموذجًا بنافذة أكبر. |
content_moderation | — | حُظر الطلب أو الإجابة بواسطة مرشح المحتوى لدى المزوّد. أعد صياغته أو اختر نموذجًا آخر. |
invalid_request | — | لم يُتعرَّف على السبب. راجع الطلب بالرجوع إلى مرجع API؛ وإذا كان صحيحًا، فتواصل مع الدعم وأرفق request_id من الاستجابة. |
ترويسات الاستجابة
| المعلمة | النوع | الوصف |
|---|---|---|
x-pv-cost-rub | string | تقدير تقريبي للتكلفة بالروبل. في البث المتدفّق، يتوفر x-pv-cost-rub عندما يكون تقدير المدخلات معروفًا؛ أما pv_cost_rub في حدث الاستخدام النهائي فيتطلب x-pv-cost: 1. ويضم سجل الاستخدام المبلغ المخصوم الفعلي. |
x-pv-generation-id | string | معرّف سجلّ الاستخدام (GET /v1/generations/{id}). يُعاد فقط لطلبات chat/completions غير المتدفّقة. |
x-pv-dropped-params | string | معاملات الطلب المفصولة بفواصل والتي لا يقبلها المسار المحدد فلم تُرسَل إلى النموذج (مثل temperature,top_p). تظهر فقط عند حجب شيء فعليًا، في الردود والأخطاء على حد سواء. نحن لا نحجب أي معامل بصمت: فعدم وجود الترويسة يعني أن كل ما أرسلته وصل إلى النموذج دون تغيير. |
Retry-After | integer | عدد الثواني المطلوب الانتظار. تضبطه الحافة عند حد 429 للمعدل، و429 للتزامن (5)، و503 للتحميل العام (2)، وبعض حالات 402 العابرة. ولا يُفترض وجوده لكل 429/503. |
الأخطاء قبل بدء الاستجابة وبعدها
البث البطيء (stream: true) يتلقّى تعليقات 200 و: pv-keepalive بعد 5 ثوانٍ من الصمت حتى لا تبدو الاتصال ميتًا؛ أما الطلب الطويل غير المتدفق فيتلقّى 200 ومسافات بيضاء بعد أول رمز له. من ذلك الحين لا يمكن أن تتغير الحالة، ويصل الخطأ في متن الاستجابة. إذا كان عميلك يتحول عند خطأ HTTP إلى مورد آخر، فأرسل x-pv-honest-errors: 1 (أو اطلب من الدعم تمكينه للحساب): عندئذٍ لا يوجد keepalive ولا 200 مبكر قبل أول بايت من الاستجابة، وكل فشل هو حالة HTTP عادية مع متن JSON. الثمن هو مقبس صامت حتى أول رمز؛ ويجب أن تغطي مهلة ترويستك هذه الفترة.
الخطأ الذي يقع بعد بدء الاستجابة هو حدث نهائي واحد: في حال الدردشة event: error مع {"error":{message,type,code,status},"choices":[{"finish_reason":"error"}]} يتبعه data: [DONE]؛ وفي /v1/responses يأتي event: response.failed حاملًا نفس error؛ وفي /v1/messages يأتي event: error الخاص بـ Anthropic. يمثل code السبب البرمجي، وstatus حالة HTTP التي كان الخطأ سيعيدها قبل بدء الاستجابة.
stream: true) لا يُعاد x-pv-generation-id لأن الفوترة تكتمل بعد انتهاء البث. راجع سجل الطلبات عبر GET /v1/generations.حدود المعدل والتزامن
يعتمد كلا الحدّين على الرصيد الحالي للحساب، وينطبقان على جميع مفاتيح API التابعة له مجتمعةً. يُعاد احتساب الفئة تلقائيًا: عند إضافة رصيد يرتفع الحد؛ وعند انخفاض الرصيد دون عتبة معينة تنخفض الفئة. لا يوجد حد لعدد الرموز في الدقيقة (TPM).
| الرصيد بدءًا من | الطلبات في الدقيقة (RPM) | الطلبات المتزامنة |
|---|---|---|
| 0 $ | 300 | 10 |
| 1 $ | 1 100 | 50 |
| 2 $ | 6 600 | 300 |
| 4 $ | 19 800 | 900 |
| 12 $ | 44 000 | 2 000 |
| المعلمة | النوع | الوصف |
|---|---|---|
429 rate_limit_exceeded | RPM | أرسل الحساب خلال آخر 60 ثانية (نافذة متحركة) عددًا من الطلبات يساوي الحد الذي تسمح به فئته. يشير Retry-After إلى عدد الثواني المتبقية حتى تتاح خانة في النافذة (1 على الأقل)؛ ويشير x-ratelimit-limit-requests إلى حد الطلبات في الدقيقة (RPM) الحالي لديك. المتن: error.cause = key_rate_limited, error.details = { enforced_by: "getvibe", limit, unit: "requests_per_minute", retry_after_seconds }. |
429 inflight_client_cap | concurrency | عدد الطلبات قيد التنفيذ حاليًا يساوي الحد الذي تسمح به الفئة. يحتفظ الطلب بخانته حتى ينتهي؛ ويحتفظ التدفق بها حتى آخر حدث فيه. Retry-After: 5. المتن: error.cause = account_concurrency_limited, error.details = { enforced_by: "getvibe", limit, unit: "parallel_requests", retry_after_seconds: 5 }. |
Personal limit | RPM | إذا كان للحساب حد مخصص للطلبات، فلا يمكنه إلا خفض حد الطلبات في الدقيقة (RPM) للفئة، ولا يمكنه رفعه مطلقًا. |
503 overloaded | service | هذا ليس حدك، بل إجراء لحماية الخدمة: يشير Retry-After: 2 إلى الحد الأقصى العام لجميع الحسابات، ويعني Retry-After: 1 أن أحد الخوادم مشغول. أعد المحاولة بعد الانتظار. |
429 from a provider | upstream | يعني error.cause = supplier_rate_limited أن مزود النموذج قيّد معدل الطلب وأن حدك الخاص لم يُستنفد؛ ويشير channel_rate_limited إلى الحد الأقصى المشترك لقناة مزود (Retry-After: 10، لم يُرسل أي شيء). |
إعادة محاولة الطلبات
بالنسبة إلى استجابة قابلة لإعادة المحاولة استخدم أولاً Retry-After إن كانت موجودة. وبدون الترويسة، لا تعامل أي 429 أو 503 على أنها قابلة لإعادة المحاولة تلقائياً: تحقق من حالة HTTP ومن error.type العام، وأصلح السبب غير القابل لإعادة المحاولة، واستخدم تراجعاً محدوداً فقط للأخطاء العابرة.
import time, requests
def call_with_retry(url, headers, payload, max_retries=5):
for attempt in range(max_retries):
r = requests.post(url, headers=headers, json=payload)
if r.status_code == 429:
# honor Retry-After, otherwise exponential backoff
wait = int(r.headers.get("Retry-After", 2 ** attempt))
time.sleep(wait)
continue
return r
return r