الأخطاء وحدود المعدل
صنّف نتائج الفشل، واحتفظ بالأدلة المنظمة، وأعد محاولة العمليات الآمنة ضمن حدود فقط.
عند أي فشل، احتفظ أولاً بالإشارة، وأوقف العمل المتأثر، وحدد هل النتيجة معلومة. لا تعد المحاولة إلا عندما تكون العملية آمنة للتكرار، وتسمح الحالة المنظمة بذلك، وتبقى مهلة للتطبيق.
1. صنّف موضع ظهور الفشل
| السطح | ما تلاحظه | الإجراء الأول |
|---|---|---|
| النقل | فشل اتصال أو قراءة أو خمول أو انقطاع من دون استجابة منصة | عامل النتيجة كمجهولة حتى يثبت عقد العملية أمان التكرار؛ أوقف وسيلة النقل المتأثرة وأغلقها |
| HTTP | حالة غير 2xx وجسم ErrorResponse منظم غالبًا | احتفظ بالحالة والجسم، ثم اتخذ القرار من code وretryable |
| Socket.IO | حدث error منظم مع code وmessage وretryable وtimestamp وid اختياري | أوقف تغذية الطلب أو البث الموجه قبل اتخاذ قرار التعافي |
| SDK | استثناء Batch ذو نوع، أو استدعاء Socket.IO منظم، أو رفض عام بعد الإسقاط | استخدم أغنى إشارة ذات نوع أو استدعاء متاح؛ لا تتخذ القرار من نص الاستثناء |
غياب الاستجابة ليس مساويًا لـretryable: true. كما أن
retryable: true المنظمة لا تكفي وحدها؛ فقد يظل تكرار الرفع أو البث المنقطع
غير آمن أو ملتبسًا.
2. احتفظ بحقول HTTP وSDK
تستخدم عمليات Batch REST وHTTP المباشر المحمية شكل HTTP المسمى
ErrorResponse:
| الحقل | المعنى |
|---|---|
error | معرّف قديم؛ احتفظ به للتشخيص والتوافق |
code | فئة قابلة للقراءة آليًا لاتخاذ قرار التطبيق |
detail | تفصيل بشري اختياري؛ لا تتخذ القرار من صياغته |
message | رسالة قديمة اختيارية في بعض استجابات المصادقة |
job_id | UUID اختياري لعمل Batch أو تدفق Realtime HTTP مرتبط بالفشل |
request_id | معرّف ارتباط اختياري لطلب Batch |
retryable | هل يصنف الخادم فشل هذا الطلب قابلاً لإعادة المحاولة |
timestamp | توقيت الخادم |
data | دليل منظم اختياري للحد أو التحقق؛ احتفظ بحقوله ووحداته |
يعني مثال Batch المتحقق منه هذا «صحح الجسم متعدد الأجزاء ولا تعده من دون تغيير»:
{
"error": "error.api.error.multipart.file.missing",
"code": "VALIDATION_REQUIRED_FIELD",
"detail": "error.api.error.multipart.file.missing",
"retryable": false,
"timestamp": "2026-01-15T10:30:00Z"
}تحقق دائمًا من حالة HTTP قبل اختيار محلل النجاح. احتفظ بالجسم الخام عندما يفشل التحليل المنظم.
يعرض SDK 0.18.0 إسقاطات مختلفة:
| سطح SDK | المعلومات المنظمة |
|---|---|
| Batch في JavaScript | يعرض BatchTranscribeError القيم statusCode وpayload وcode وretryable وjobId وdetail وtimestamp وcapacity وrawBody؛ وتضيف أخطاء حد المعدل retryAfter |
| Batch في Python | يعرض BatchTranscribeError القيم status_code وpayload وcode وretryable وjob_id وdetail وtimestamp وcapacity وraw_body؛ وتضيف أخطاء حد المعدل retry_after |
| استدعاءات Socket.IO | يحتفظ ErrorResponse في SDK بالقيم الاختيارية id وmessage وcode وretryable وtimestamp وretry_after_seconds وdata وreason وretry_scope |
| رفض TTS بسبب خطأ الخادم | ترفض JavaScript بـError عام، وترفع Python RuntimeError عامًا؛ يحتفظ الرفض بالرسالة فقط، لذلك سجل الحقول المنظمة في onError / on_error |
| رموز حدود العمل | يحتفظ SDK 0.18.0 بالحقل data، ويصنف رموز الحدود الحالية، ويوجه الرفض الحامل للمعرّف إلى سياق الطلب النشط. يظل الاستدعاء العام يعمل أولًا، ثم يُرفض استدعاء التوليف بخطئه العام الذي يحتفظ بالرسالة فقط. |
| رموز سياسة محتوى TTS | يصدر SDK 0.18.0 الثابتين TTS_INPUT_NOT_ALLOWED وTTS_MODERATION_UNAVAILABLE، ويصنفهما على أنهما مملوكان لـTTS، ويوجه الخطأ الحامل للمعرّف إلى سياق التوليف النشط |
استمر في التحقق من دخل TTS قبل الإرسال، ومرّر دائمًا مهلة صريحة
(timeoutSeconds في JavaScript وtimeout_seconds في Python). اقرأ code
وdata من استدعاء الخطأ العام قبل رفض الطلب؛ فالاستثناء العام يحتفظ بالرسالة
فقط.
3. طبّق جدول القرار
| الحالة المرصودة | تفسير النتيجة | الإجراء |
|---|---|---|
400 أو رمز تحقق | الطلب غير صالح | صحح UUID أو المعاملات أو التأطير أو الملف أو الصوت؛ لا تعده من دون تغيير |
401 أو رمز مصادقة | المفتاح مفقود أو غير صالح | صحح بيانات الاعتماد قبل طلب آخر |
403 مع AUTH_FORBIDDEN | قبلت المنصة المفتاح لكنه لا يملك القدرة | حدّث الوصول عبر مسار إدارة المفاتيح في مؤسستك؛ لا تعد الطلب من دون تغيير |
استجابة 403 أخرى | رفضت بوابة أو طبقة وسيطة الطلب | احتفظ بالجسم الخام أو معرّف الدعم، ثم تحقق من العنوان والمسار وبيانات الاعتماد وأي ترويسات خاصة بالنشر |
404 / TRANSCRIPTION_JOB_NOT_FOUND | المهمة المطلوبة غير متاحة تحت UUID ذلك | أوقف الاستعلام عن UUID ذلك، وتحقق من المعرّف المخزن |
405 / METHOD_NOT_ALLOWED | المسار أو الطريقة خطأ | صحح التوجيه قبل طلب آخر |
Realtime TTS 422 / CHARACTER_COUNT_EXCEEDED | النص، أو نص مرجع الصوت، أطول من الحد المسموح. يحدد data.bound أيهما: tts_input_characters أو tts_voice_reference_text_characters | اختصر النص بالاستناد إلى data.limit، ولا تعد الطلب نفسه بلا تغيير |
Realtime TTS 422 / VOICE_REFERENCE_COUNT_EXCEEDED | أكثر من عنصر واحد في voice_references؛ يُقبل عنصر واحد فقط | أرسل مرجعًا واحدًا، ولا تعد الطلب نفسه بلا تغيير |
Realtime TTS 422 / AUDIO_DURATION_EXCEEDED مع data.bound بقيمة tts_voice_reference_duration | مقطع المرجع أطول من حد المرجع المضبوط في النشر، وقد يضبطه النشر أقل من حد النموذج نفسه | اقتطع المقطع إلى data.limit ثانية — وdata.limit هي المرجع لا أي قيمة افتراضية منشورة، ولا تعد الطلب نفسه بلا تغيير |
Realtime TTS 413 / PAYLOAD_TOO_LARGE مع data.bound بقيمة tts_voice_reference_bytes | الحجم المفكوك لمقطع المرجع يتجاوز الحد | أرسل مقطعًا أقصر أو بمعدل عينات أقل، ولا تعد الطلب نفسه بلا تغيير |
TTS 400 / TTS_INPUT_NOT_ALLOWED | رفضت سياسة المحتوى النص؛ ولن يُقبل النص نفسه | غيّر النص قبل إرسال طلب آخر، ولا تعده بلا تغيير |
TTS 503 / TTS_MODERATION_UNAVAILABLE | تعذر على جهة الإشراف على المحتوى اتخاذ قرار، فأوقف التوليف بصورة مغلقة | لا تعامل الحالة كرفض لسياسة المحتوى. لا تعد المحاولة إلا بعد تراجع محدود وما دامت مهلة التطبيق باقية |
402 / CREDITS_EXHAUSTED | نفد الرصيد ولا يمكن لإعادة فورية استعادته | أوقف العمل المتأثر ولا تعد الطلب من دون تغيير. يكون الحدث في منتصف تدفق Realtime طرفيًا ويتبعه فصل. |
503 / BILLING_AUTHORIZATION_UNAVAILABLE | لم تتمكن جهة الفوترة من اتخاذ قرار، فأخفقت المنصة بصورة مغلقة | أوقف العمل المتأثر ولا تعده إلا بعد تراجع محدود. يكون الحدث في منتصف Realtime طرفيًا ويتطلب تدفقًا جديدًا. |
Realtime 409 / ASR_STREAM_EXPIRED | أنهى خمول الصوت أو فقد تسلسل الخلفية تدفق ASR هذا | اقرأ reason، وتحقق من retry_scope: "new_stream"، واحتفظ بالخرج المثبت، وابدأ UUID جديدًا؛ ولا تعِد الإطارات على المعرّف المنتهي. |
422 في Batch مع رمز تحقق مثل VALIDATION_FILE_CORRUPT | الملف غير مدعوم أو تالف أو فارغ أو بمدة صفرية | صحح الدخل؛ لا تعد البايتات نفسها |
422 / AUDIO_DURATION_EXCEEDED في Batch مع data.bound بقيمة audio_duration | الصوت صالح لكن مدته المفكوكة أطول من المدة المقبولة | قسّم التسجيل إلى data.limit ثانية أو أقل، أو أرسل ملفًا أقصر، ولا تعد الطلب نفسه بلا تغيير |
422 / FILE_COUNT_EXCEEDED في Batch | عدد الأجزاء أكبر مما يقبله الطلب الواحد. يحدد data.bound أيهما، ويبين data.unit وحدة العد: يعد file_parts الملفات الصوتية، ويعد multipart_parts كل أجزاء multipart | مع file_parts أرسل data.limit ملفًا صوتيًا على الأكثر في الطلب؛ ومع multipart_parts ابقِ النموذج كاملًا داخل data.limit جزءًا، ولا تعد الطلب نفسه بلا تغيير |
429 / RATE_LIMIT_EXCEEDED في Batch | ضغط سعة صريح | ضع عمليات الإرسال في طابور أو أبطئها، ثم استخدم سياسة إعادة محاولة محدودة |
HTTP 5xx مع retryable: true في GET لنتيجة Batch استُدعي مع save_result=true | فشلت قراءة نتيجة محفوظة | أعدها بتراجع محدود وjitter ما دامت المهلة باقية |
HTTP 5xx مع retryable: true في رفع | يدعو الخادم إلى الإعادة، لكن نتيجة الإنشاء قد تظل ملتبسة | لا تكرر بلا تمييز؛ طبق سياسة صريحة لخطر التكرار |
أي استجابة مع retryable: false | يطلب الخادم عدم إعادة حالة الطلب هذه | توقف حتى يتغير الدخل أو بيانات الاعتماد أو المسار أو الإعداد |
| مهلة قراءة قبل أي استجابة | لا يوجد تصنيف من المنصة | لا تعد إلا قراءة يحفظ عقدها النتيجة، وضمن المهلة فقط |
| خطأ أو انقطاع Realtime | قد تكون حالة البث القديم وحد الصوت المقبول ملتبسين | توقف، واحتفظ بالنتائج المثبتة، ونظف، وتعافَ بـUUID جديد إذا سمحت السياسة |
خطأ حل voice_id في TTS (SAU-2258) | voice_id المُرسَل من العميل الذي ليس UUID صالحًا هو 400 VALIDATION_INVALID_UUID؛ والصالح البنية لكنه لا يحدد صوتًا متاحًا هو 400 TTS_VOICE_NOT_FOUND (كلاهما غير قابل للإعادة). وصوت محلول بياناته المخزَّنة ناقصة أو تالفة هو 500 TTS_VOICE_RESOLUTION_FAILED غير قابل للإعادة؛ وانقطاع عابر لقاعدة البيانات/التخزين أثناء الحل هو 503 SERVER_DEPENDENCY_FAILURE قابل للإعادة. أما أخطاء النموذج/السعة/الاستدلال الحقيقية فتبقى 500 TTS_SYNTHESIS_FAILED قابلة للإعادة | صحّح voice_id أو أرسل voice_references؛ وأعد محاولة 503 و500 TTS_SYNTHESIS_FAILED فقط مع تراجع، ولا تعد أبدًا محاولة الـ400 غير القابلين للإعادة ولا 500 TTS_VOICE_RESOLUTION_FAILED |
خطأ TTS بقيمة 400 عند إرسال المحددين معًا أو مرجع مشوه | إرسال voice_id مع voice_references غير فارغة، أو مصفوفة voice_references فارغة صريحة، أو صوت مرجع ليس base64 قياسيًا صارمًا بصيغة RIFF/WAVE أحادي القناة PCM16، هو خطأ تحقق غير قابل للإعادة | في SDK، اختر واحدًا بالضبط من voice_id أو عنصر voice_references قياسي واحد. يسمح HTTP المباشر بحذف المحددين لاختيار يعتمد على النشر. لا ترسل المحددين معًا. |
قد تعيد بوابة النشر 429 لطلب Realtime HTTP، بينما قد تطوي خلفية Fast أو البث
الحي الحالية فشل سعة الصوت الداخلي إلى 500 قابلة للإعادة مع
ASR_TRANSCRIPTION_FAILED. لا تستنتج حصة Realtime أو مجموعة سعة أو نافذة
إعادة ضبط من أي من الاستجابتين أو من سعة Batch.
4. عامل Batch 429 كضغط سعة
يتضمن 429 في Batch الحقول المنظمة المعتادة إضافة إلى data.capacity:
{
"error": "error.rate_limit",
"code": "RATE_LIMIT_EXCEEDED",
"detail": "error.rate_limit",
"retryable": true,
"timestamp": "2026-01-15T10:30:00Z",
"data": { "capacity": 120.5 }
}capacity هي السعة المتبقية مقاسة بثواني الصوت. استخدمها لقرارات الطابور
والقبول. وهي ليست حصة موثقة أو نافذة إعادة ضبط أو عدد ثوانٍ للانتظار.
لا يَعِد عقد OpenAPI بترويسة Retry-After. لا تُملأ
retryAfter / retry_after في SDK إلا عندما توجد ترويسة صالحة فعلاً. عند
غيابها، طبق تراجعًا أسيًا محدودًا مع jitter. قيّد دائمًا المحاولات، وكل تأخير،
وزمن إعادة المحاولة الكلي، وتزامن المنتجين بمهلة كلية.
5. احفظ نتيجة Batch قبل إعادة قراءتها
لا يعيد SDK المنشور محاولات Batch. الخيار maxRetries / max_retries مهمل
ومتجاهل ومحتفظ به للتوافق فقط. تعيد هذه الأمثلة المختبرة
getResult() / get_result()، لا الرفع، وتمرر صراحة
saveResult: true / save_result=True. قد تمسح القيمة الافتراضية false
النتيجة النهائية بعد بناء الاستجابة، ولذلك قد تتبع الاستجابة المفقودة حالة
cleared. يتيح خيار الحفظ إعادة محدودة لكنه لا يحدد مدة احتفاظ. تستخدم الأمثلة
الخصائص ذات النوع المنشورة:
import {
BatchTranscribeClient,
BatchTranscribeError,
BatchTranscribeRateLimitError,
Language,
type TranscriptionResponse,
} from '@humain-voice/sdk';
function requiredEnv(name: 'API_KEY' | 'API_URL'): string {
const value = process.env[name];
if (!value) throw new Error(`${name} is required`);
return value;
}
async function pause(milliseconds: number): Promise<void> {
await new Promise<void>((resolve) => setTimeout(resolve, milliseconds));
}
async function getResultWithRetry(
client: BatchTranscribeClient,
jobId: string,
attempts = 5,
): Promise<TranscriptionResponse> {
for (let attempt = 1; attempt <= attempts; attempt += 1) {
try {
// saveResult prevents a terminal read from clearing the stored result
// before a retry. It does not establish a retention duration.
return await client.getResult(jobId, Language.ArEn, { saveResult: true });
} catch (error: unknown) {
if (!(error instanceof BatchTranscribeError)) throw error;
const rateLimited = error instanceof BatchTranscribeRateLimitError;
const retryable = rateLimited || error.retryable === true;
console.error({
statusCode: error.statusCode,
code: error.code,
capacity: error.capacity,
});
if (!retryable || attempt === attempts) throw error;
const serverDelayMs = rateLimited && error.retryAfter !== undefined
? error.retryAfter * 1_000
: 0;
const exponentialDelayMs = 500 * 2 ** (attempt - 1);
await pause(Math.max(serverDelayMs, exponentialDelayMs) + Math.random() * 250);
}
}
throw new Error('Retry loop exhausted');
}
async function main(): Promise<void> {
const jobId = process.argv[2];
if (!jobId) throw new Error('Pass a batch job ID as the first argument');
const client = new BatchTranscribeClient({
api_url: requiredEnv('API_URL'),
api_key: requiredEnv('API_KEY'),
});
try {
const result = await getResultWithRetry(client, jobId);
console.info(result.status, result.results?.transcript ?? '');
} finally {
await client.close();
}
}
void main().catch((error: unknown) => {
console.error(error);
process.exitCode = 1;
});
السلوك المتوقع: تستخدم القراءات القابلة للإعادة خمس محاولات على الأكثر، وتحترم
قيمة retryAfter / retry_after فعلية عند وجودها، وتضيف تأخيرًا أسيًا وjitter،
وتعيد إطلاق الفشل النهائي. لا يغني حد المحاولات عن مهلة كلية للتطبيق.
6. أبقِ العمليات الملتبسة خارج الإعادة الآلية
رفع الملفات الكاملة
لا يوثق إنشاء عمل Batch وإرسال الصوت الكامل عبر Fast عقد مفتاح idempotency. لا تثبت المهلة أو الانقطاع بعد إرسال البايتات النجاح أو الفشل؛ فقد يكون الخادم قبل الطلب.
إذا عاد jobId أو UUID للطلب، فاحتفظ به وتابع مسار النتيجة المعتاد لتلك
العملية. ومن دون استجابة حاسمة، سجل المحاولة الملتبسة ولا تكرر إلا وفق سياسة
تطبيق تقبل صراحة العمل المكرر.
بث Realtime
لا تعرّف عقود Socket.IO وHTTP العامة استئنافًا شفافًا ولا إعادة idempotent للإطارات. عند خطأ أو انقطاع:
- أوقف إرسال الصوت وأغلق البث أو الاستجابة القديمة.
- احتفظ بالنتائج المثبتة وتجاهل الحالة المؤقتة غير المحسومة.
- سجل فترة الصوت الملتبسة.
- أعد الاتصال بتراجع محدود وUUID جديد فقط إذا سمح الخطأ ومهلة التطبيق.
- افصل البث الجديد حتى يوفق التطبيق الخطين الزمنيين صراحة.
لا تعد الإطارات القديمة أو تستخدم UUID القديم بافتراض إزالة الخادم لتكرارها.
7. افصل المهل عن المهلة الكلية
| التحكم | ما يقيّده | ما يثبته الانتهاء |
|---|---|---|
| مهلة الاتصال أو الطلب | مرحلة شبكة أو طلب واحد | توقف العميل عن الانتظار؛ لا تثبت هل نفذ الخادم أم لا |
| مهلة القراءة أو الخمول | انتظار البايت أو المقطع أو الحدث التالي | لم يصل تقدم في تلك الفترة؛ لا تثبت مدة العملية الكلية |
| مهلة انتظار Realtime النهائي | الانتظار بعد إطار الدخل النهائي | انتهى الانتظار؛ لا تثبت وصول نتيجة نهائية |
| مهلة التطبيق الكلية | الاتصال والعمل والإعادات والتأخيرات والتنظيف معًا | يجب أن يوقف التطبيق مزيدًا من العمل |
تكون قيمة timeoutSeconds في TTS لـJavaScript افتراضيًا 30 ثانية من الخمول
أثناء انتظار كل مقطع صوت. لا يضع TTS في Python مهلة ما لم تمرر
timeout_seconds. ينتظر close() في Realtime ASR SDK is_final على مستوى البروتوكول أو
خطأ موجهًا أو مهلة الإغلاق فقط، ويمكنه العودة عند انتهاء ذلك الانتظار. لا يغني
أي من هذه الضوابط عن المهلة الكلية.
بعد أي انتهاء، نظف داخل finally: ألغِ قراءات HTTP وأغلق أجسام الاستجابة؛
وأوقف صوت Socket.IO واستدعِ disconnect() أو اخرج من سياق Python غير
المتزامن؛ وأغلق عميل Batch. لا تستنتج أن تنظيف العميل ألغى العمل على الخادم.
ولا تستنتج أنه ألغى توليف TTS جارٍ.
8. سجل القرارات واختبر مسارات الفشل
سجل العملية، ووسيلة النقل، وحالة HTTP أو اسم الحدث، وcode، وقرار إعادة
المحاولة، وUUID للطلب أو العمل، ورقم المحاولة، والمهلة المتبقية، ونوع المهلة،
وسعة Batch عند وجودها. لا تسجل مفاتيح API أو الصوت الكامل أو نصًا حساسًا
افتراضيًا.
بعد ذلك، شغّل مثال القراءة الآمنة، ثم اختبر الدخل غير الصالح، والمصادقة،
و429 الصريح، ومهلة القراءة، ومهلة رفع ملتبسة، وانقطاع Realtime، وانتهاء
انتظار النتيجة النهائية، والتنظيف في بيئة اختبار معزولة.