שגיאות
כל שגיאה שה-SDK של Nodaro ל-TypeScript זורק: סטטוס ה-HTTP, הקוד והשדות, ומה עושים במחסור בקרדיטים, במגבלות קצב, בהתנגשויות ובמשימות שנכשלו.
כל שגיאה שה-SDK של Nodaro זורק בעקבות תשובה של ה-API היא מופע של NodaroError או של אחת מתת־המחלקות שלה. בקשה שנכשלת עם סטטוס שגיאה זורקת את תת־המחלקה שמתאימה לסטטוס. פונקציות העזר שמריצות וממתינות זורקות תת־מחלקות משלהן כשמשימה נכשלת, חורגת מהזמן או נעצרת. תפסו קודם את המחלקות הספציפיות, ואת NodaroError בסוף.
כל מחלקות השגיאה
| מחלקה | סטטוס | code | שדות נוספים | מתי היא נזרקת |
|---|---|---|---|---|
NodaroError | כל סטטוס | הקוד של השרת | מחלקת הבסיס, וכל שגיאה שאין לה מחלקה ספציפית יותר | |
UnauthorizedError | 401 | unauthorized | האסימון חסר, פג תוקפו או לא תקין | |
ForbiddenError | 403 | forbidden | missingScope? | הגישה נדחתה, או שלאסימון OAuth חסרה הרשאה |
ModelUnavailableError | 403 | model_not_available או model_disabled | המודל שבחרתם לא מוצע, או שמנהל כיבה אותו | |
ImportRefusedError | 403 | imports_blocked, import_source_disabled או קוד rights_* | ייבוא של קישור נדחה עוד לפני שהתוכן נמשך | |
NotFoundError | 404 | not_found | הפריט לא קיים, או שאין לכם גישה אליו | |
RateLimitedError | 429 | rate_limited | יותר מדי בקשות | |
InsufficientCreditsError | 402 | insufficient_credits או קוד 402 אחר | required?, available? | החשבון לא יכול לשלם על ההרצה |
CreditCapExceededError | 402 | budget_exceeded, member_cap_exceeded או user_allowance_exceeded | required?, available? | ההרצה חורגת מתקרת הוצאה שמישהו אחר קבע |
StorageExceededError | 413 | storage_exceeded | limitBytes?, reason? | מה ששלחתם לא נכנס: האחסון מלא, או שקובץ אחד חורג מהמגבלה |
WorkflowConflictError | 409 | workflow_conflict או production_busy | currentUpdatedAt?, currentVersion?, currentRecord? | מישהו אחר שינה את הפריט לפניכם |
AlreadyRunningError | 409 | already_running | executionId | ההרצה שביקשתם להתחיל או להמשיך עדיין רצה |
AppRunVersionChangedError | 409 | app_run_version_changed | runVersion?, appVersion? | ניסיון חוזר של הרצת אפליקציה נדחה, כי האפליקציה עברה לגרסה אחרת |
JobBlockedError | 422 | job_blocked | מדיניות התוכן של הפריסה דחתה את הבקשה | |
StudioOpError | 4xx | הקוד של השרת | opIndex | פעולה אחת באצווה של Studio נדחתה |
JobFailedError | 0 | job_failed | jobId, jobStatus | משימה שחיכיתם לה נכשלה או בוטלה |
JobTimeoutError | 0 | job_timeout | jobId, timeoutMs | משימה לא הסתיימה בתוך maxMs |
JobAbortedError | 0 | job_aborted | jobId? | ההמתנה בוטלה דרך ה-AbortSignal שלכם |
JobHeldError | 0 | job_held | jobId | משימה ממתינה לבדיקה של אדם |
StudioPreviewUnavailable | 0 | studio_preview_unavailable | הפריסה לא יכולה להציג תצוגה מקדימה של אצווה של Studio | |
StudioPreviewAppliedError | 0 | studio_preview_applied | applied | אצווה של Studio שביקשתם לראות בתצוגה מקדימה הוחלה בפועל |
לכל מחלקה יש ארבעה שדות: message, משפט קריא; code, מחרוזת קבועה שאפשר להשוות אליה; status, סטטוס ה-HTTP; ו-details. הערך 0 ב-status פירושו שהשגיאה לא הגיעה מתשובת HTTP. למשל, את JobTimeoutError זורקת לולאת התשאול של ה-SDK עצמו.
ב-details נמצאים כל השדות של מעטפת השגיאה מלבד code ו-message, כפי שהשרת שלח אותם. למשל, slot כשטרנד נדחה, reasons כשפרסום נדחה ו-issues כשהקלט לא תקין. הערך הוא {} כשלא היה במעטפת שום דבר נוסף, וגם בשגיאה שה-SDK יצר בעצמו.
try {
await client.trends.run(slug, request)
} catch (err) {
if (err instanceof NodaroError && err.code === "missing_slot") askFor(err.details.slot as string)
}הבנאי הוא new NodaroError(message, code, status, details?).
חלק מהסטטוסים ממופים למחלקה אחת, בלי קשר לקוד שהשרת שלח. שגיאת 403 הופכת ל-ForbiddenError עם code בערך forbidden, חוץ מדחייה של מודל, שהופכת ל-ModelUnavailableError, ומדחייה של ייבוא קישור, שהופכת ל-ImportRefusedError. שגיאת 404 הופכת ל-NotFoundError, וכל שגיאת 413 הופכת ל-StorageExceededError. במקרים האלה, את הסיבה של השרת קוראים ב-message. שגיאת 409 הופכת ל-WorkflowConflictError רק עם הקוד workflow_conflict או production_busy. שגיאת 409 עם already_running שמציינת executionId הופכת ל-AlreadyRunningError, ושגיאת 409 עם app_run_version_changed הופכת ל-AppRunVersionChangedError. שגיאות עם כל סטטוס אחר, כגון 400 או 503, ושגיאת 409 עם כל קוד אחר, מגיעות כ-NodaroError עם ה-code של השרת עצמו.
תפיסת שגיאות לפי הסדר
import {
ForbiddenError,
InsufficientCreditsError,
ModelUnavailableError,
NodaroError,
NotFoundError,
RateLimitedError,
StorageExceededError,
UnauthorizedError,
} from "@nodaro/sdk"
try {
await client.workflows.run(workflowId)
} catch (err) {
if (err instanceof UnauthorizedError) {
redirectToLogin()
} else if (err instanceof ModelUnavailableError) {
showError("This model is not available. Choose another model.")
} else if (err instanceof ForbiddenError) {
if (err.missingScope) requestAdditionalScopes([err.missingScope])
else showError("You do not have permission to do this.")
} else if (err instanceof InsufficientCreditsError) {
showCreditPaywall({ required: err.required, available: err.available })
} else if (err instanceof RateLimitedError) {
await retryWithBackoff()
} else if (err instanceof StorageExceededError) {
if (err.reason === "file_too_large") showError("This file is too large.")
else showError(`Storage limit of ${err.limitBytes} bytes reached.`)
} else if (err instanceof NotFoundError) {
showError("Not found.")
} else if (err instanceof NodaroError) {
console.error(`API error ${err.status} (${err.code}): ${err.message}`)
} else {
throw err // a network failure or a timeout, not an API answer
}
}כשבקשה חורגת מ-timeoutMs של הלקוח, או כשיש כשל רשת, ה-Promise נדחה עם שגיאה של סביבת הריצה עצמה, כגון AbortError או TypeError. השגיאות האלה הן לא מופעים של NodaroError.
אימות והרשאות
UnauthorizedError
HTTP 401. האסימון חסר, פג תוקפו או לא תקין. קבלו אסימון חדש, או בקשו מהמשתמש להתחבר שוב, ואז נסו שוב.
ForbiddenError
HTTP 403. למי שקרא אין הרשאה לפעולה הזו. כשאסימון OAuth לא קיבל הרשאה שנקודת הקצה דורשת, השדה missingScope מציין את ההרשאה הזו, למשל workflows:execute. בקשו מהמשתמש לאשר אותה, ואז נסו שוב עם האסימון החדש. ראו את הסעיף הרשאות (scopes) והרשאות חסרות בדף אימות.
סיבות אחרות הן, למשל, מהדורה שלא כוללת את היכולת או תפקיד נמוך מדי. כולן מגיעות עם code בערך forbidden, ולכן הציגו את message כדי להסביר מה הסיבה.
ModelUnavailableError
HTTP 403 שדוחה את המודל, ולא את מי שקרא. Nodaro עונה כך עוד לפני שמשוריינים קרדיטים. בחרו מודל אחר: ניסיון חוזר, טעינת קרדיטים או הרשאה רחבה יותר לא ישנו כלום.
code | סיבת הדחייה |
|---|---|
model_not_available | הפריסה הזו לא מציעה את המודל. המודל לא כלול במהדורה או בממשק שלה, או שמנהל השרת הסתיר אותו. |
model_disabled | מנהל כיבה את המודל. |
המחלקה ModelUnavailableError מרחיבה את ForbiddenError, ולכן בדיקת instanceof ForbiddenError שכבר יש בקוד שלכם עדיין תופסת אותה. כדי להבחין בין השתיים, בדקו קודם instanceof ModelUnavailableError. השתמשו ב-code כדי להציג משפט משלכם, ולא ב-message באנגלית. הקבוע MODEL_UNAVAILABLE_CODES, מטיפוס ReadonlySet<ModelUnavailableCode>, מפרט את שני הקודים. השגיאה לא מציינת את המודל: המודל שנדחה הוא ה-provider של הבקשה שלכם, או אחד מה-models שלה, כשהבקשה מריצה כמה מודלים. שגיאת 403 עם insufficient_scope, עם כל קוד אחר או בלי קוד נשארת ForbiddenError רגילה.
הבנאי הוא new ModelUnavailableError(code, message?). הבנאי של ForbiddenError הוא new ForbiddenError(message?, missingScope?, code?).
ImportRefusedError
HTTP 403 שדוחה ייבוא של קישור, עוד לפני שהתוכן נמשך: media.downloadVideo(), uploads.importUrl() וייבואי האודיו. הסירוב הגיע מאמצעי שהוחל על החשבון, מבדיקת זכויות התוכן או ממדיניות האתרים של הפריסה. ראו את דף ה-API זכויות תוכן ואת הסעיף מפרים חוזרים באותו דף.
code | סיבת הדחייה |
|---|---|
imports_blocked | ייבוא קישורים חסום בחשבון, או שהחשבון סגור, לפי מדיניות המפרים החוזרים של הפריסה. ההודעה מציינת עד מתי: תאריך לפי UTC, או עד שמנהל יסיר את החסימה. |
import_source_disabled | הפריסה לא מאפשרת ייבוא מהאתר של הקישור. ההודעה לא מציינת שום אתר. |
rights_confirmation_required | הפריסה דורשת אישור, ולא נשלח אישור. |
rights_authorization_required | הפריסה דורשת אישור, הייבוא הגיע דרך מפתח API, אפליקציה מחוברת או סוכן AI, ולחשבון אין הרשאה קבועה. בעל החשבון נותן את ההרשאה מתוך הסשן שלו, עם contentRights.authorize(). |
rights_confirmation_not_found | אין אישור עם המזהה הזה. |
rights_confirmation_mismatch | האישור שייך לקישור אחר או לחשבון אחר. |
rights_confirmation_stale | ההצהרה השתנתה. טענו אותה שוב ואשרו שוב. |
rights_confirmation_expired | האישור ישן יותר משעה. |
rights_confirmation_used | האישור כבר נוצל לייבוא. גם ייבוא שנכשל אחרי שמשיכת התוכן התחילה מנצל את האישור. |
כשהקוד הוא rights_confirmation_*, קראו שוב ל-client.contentRights.confirm({ url, declarationVersion }) וייבאו שוב עם המזהה החדש. המחלקה ImportRefusedError מרחיבה את ForbiddenError, ולכן בדיקת instanceof ForbiddenError שכבר יש בקוד שלכם עדיין תופסת אותה. בדקו קודם instanceof ImportRefusedError, והשתמשו ב-code כדי להציג משפט משלכם. הקבוע IMPORT_REFUSAL_CODES, מטיפוס ReadonlySet<ImportRefusalCode>, מפרט את הקודים. הבנאי הוא new ImportRefusedError(code, message?).
NotFoundError
HTTP 404. הפריט לא קיים, או שמי שקרא לא יכול לראות אותו. Nodaro עונה באותה דרך בשני המקרים, ולכן מזהה אף פעם לא מגלה אם קיים משהו שאין לכם גישה אליו. משאב שקיים רק ב-Nodaro Cloud, כגון הפקות Studio או Recast, מחזיר 404 גם בהתקנה באירוח עצמי.
קרדיטים, אחסון ומגבלות
InsufficientCreditsError
HTTP 402. החשבון לא יכול לשלם על ההרצה, ולכן שום דבר לא התחיל. השדה required הוא מספר הקרדיטים שההרצה צריכה, והשדה available הוא מספר הקרדיטים שיש בחשבון, או, כשמדובר בתקרה, מה שנשאר בה. Nodaro Cloud ממלא את שניהם, אבל הטיפוס מסמן אותם כאופציונליים. השדה code הוא הקוד של הדחייה עצמה: הקוד insufficient_credits כשהבעיה היא היתרה שלכם וגם כשהשרת לא שלח קוד, ואחרת קוד 402 אחר, כגון free_video_limit או insufficient_app_credits.
try {
await client.nodes.runAndWait("generate-video", params)
} catch (err) {
if (err instanceof InsufficientCreditsError) {
console.log(`Need ${err.required} credits, have ${err.available}`)
}
}בדקו את היתרה לפני הרצה עם client.credits.balance(). ראו את הדף קרדיטים.
CreditCapExceededError
HTTP 402 בגלל תקרת הוצאה שמישהו אחר קבע, ולא בגלל היתרה שלכם. טעינת קרדיטים לא תעזור: מי שקבע את התקרה צריך להגדיל אותה.
code | התקרה |
|---|---|
budget_exceeded | התקציב של סביבת העבודה |
member_cap_exceeded | תקרת הקרדיטים שלכם בסביבת העבודה הזו |
user_allowance_exceeded | המכסה של הפריסה לכל משתמש |
המחלקה CreditCapExceededError מרחיבה את InsufficientCreditsError, ולכן בדיקת instanceof InsufficientCreditsError שכבר יש בקוד שלכם עדיין תופסת אותה. כדי להבחין בין השתיים, בדקו קודם instanceof CreditCapExceededError. הקבוע CREDIT_CAP_CODES, מטיפוס ReadonlySet<CreditCapCode>, מפרט את שלושת הקודים.
StorageExceededError
HTTP 413. מה ששלחתם לא נכנס. כל שגיאת 413 מגיעה כמחלקה הזו, בכל נתיב, והשדה reason מציין באיזה סוג מדובר:
reason | משמעות |
|---|---|
storage_limit_exceeded | האחסון של החשבון מלא. השדה limitBytes הוא המגבלה. מחקו מדיה שאתם כבר לא צריכים, ואז נסו שוב. |
file_too_large | קובץ אחד חורג ממגבלת הגודל. האחסון לא מלא. שלחו קובץ קטן יותר. |
payload_too_large, post_too_large, duration_exceeded | הבקשה, הפוסט או אורך המדיה חורגים ממגבלה. האחסון לא מלא. |
כשבתשובה לא היה קוד, השדה reason הוא undefined. העלאות והעתקות לאחסון שלכם, כגון שכפול מספריית הקהילה, זורקות את השגיאה הזו. הבנאי הוא new StorageExceededError(message?, limitBytes?, reason?).
RateLimitedError
HTTP 429. שלחתם יותר מדי בקשות. המתינו, ואז נסו שוב עם המתנה שהולכת ומתארכת: למשל 2 שניות, אחר כך 4 ואחר כך 8. הפסיקו אחרי כמה ניסיונות. ראו את דף ה-API מגבלות קצב.
המתנה למשימות
המתודות client.nodes.runAndWait() ו-client.nodes.runMany(), ופונקציות העזר ...AndWait של משאבים אחרים בודקות את הסטטוס של משימה מדי כמה שניות, עד שהיא מסתיימת. בזמן ההמתנה הן זורקות את השגיאות האלה.
JobFailedError
המשימה הסתיימה בסטטוס failed או cancelled. השדה jobStatus מציין איזה מהשניים, השדה jobId מזהה את המשימה, והשדה message כולל את הודעת השגיאה של המשימה עצמה. קבלו את המשימה המלאה עם client.jobs.get(err.jobId): השדה error_hint שלה מסביר חסימה של מסנן בטיחות או של מדיניות.
JobTimeoutError
המשימה לא הגיעה לסטטוס סופי בתוך maxMs, שהוא 15 דקות כברירת מחדל. המשימה לא מבוטלת. בדרך כלל היא בכל זאת מסתיימת בשרת ונשמרת בספרייה שלכם. בדקו אותה מאוחר יותר עם client.jobs.get(err.jobId), או העבירו maxMs גדול יותר למודלים איטיים. משימה שנמצאת בהתאוששות מדווחת recovering: true בסטטוס שלה, וההתאוששות יכולה לקחת עשרות דקות.
JobAbortedError
ההמתנה בוטלה דרך ה-AbortSignal שלכם. ה-SDK מפסיק מיד לבדוק את הסטטוס. המשימה לא מבוטלת. כדי לעצור אותה בשרת ולקבל החזר על הקרדיטים ששוריינו לה, קראו ל-client.jobs.cancel(err.jobId).
JobHeldError
המשימה הגיעה לסטטוס pending_review: מדיניות תוכן של הפריסה הזו מעכבת את התוצאה עד שאדם יבדוק אותה. ה-SDK מפסיק לחכות כבר בפעם הראשונה שהוא רואה את הסטטוס הזה. המשימה לא מבוטלת, והקרדיטים שלה נשארים משוריינים במהלך הבדיקה. אל תריצו את הבקשה שוב, כי גם בקשה כפולה תמתין לבדיקה.
בדקו את המשימה מאוחר יותר עם client.jobs.get(err.jobId). היא מסתיימת בסטטוס completed כשהבודק מאשר אותה, בסטטוס failed כשהבודק דוחה אותה, או בסטטוס cancelled אם תבטלו אותה. במשימה שנדחתה יש error_hint.kind בערך policy-block, ו-reason שאפשר להציג כמו שהוא. השגיאה הזו קורית רק בפריסות שרושמות מדיניות משימות.
JobBlockedError
HTTP 422 עם הקוד job_blocked. מדיניות תוכן של הפריסה הזו דחתה את הבקשה לפני שהיא רצה. לא נוצרה משימה ולא נגבו קרדיטים. השדה message נכתב בשביל המשתמשים שלכם, ולכן הציגו אותו כמו שהוא. אל תנסו שוב את אותה בקשה. השגיאה הזו קורית רק בפריסות שרושמות מדיניות משימות.
שינויים מקבילים
WorkflowConflictError
HTTP 409. שלחתם שינוי מותנה, ומישהו אחר שינה את הפריט לפניכם. השגיאה מגיעה עם אחד משני קודים:
- הקוד
workflow_conflict: קריאה ל-client.workflows.update()עםexpectedVersionאוexpectedUpdatedAtלא תאמה לתהליך השמור. - הקוד
production_busy: הפקת Studio המשיכה להשתנות בזמן שהשרת החיל את השינוי שלכם, והשרת הפסיק לנסות שוב.
הפתרון זהה בשני המקרים: טענו את הפריט מחדש, החילו את השינוי שלכם על העותק העדכני ושלחו אותו שוב. כשהשרת מצרף אותו, ב-currentRecord נמצא התהליך הנוכחי, ולכן אפשר למזג בלי לטעון אותו שוב.
import { WorkflowConflictError } from "@nodaro/sdk"
try {
await client.workflows.update(id, { settings, expectedVersion: loadedVersion })
} catch (err) {
if (err instanceof WorkflowConflictError && err.currentRecord) {
const merged = mergeSettings(err.currentRecord.settings, settings)
await client.workflows.update(id, { settings: merged, expectedVersion: err.currentVersion })
} else {
throw err
}
}AlreadyRunningError
HTTP 409 עם הקוד already_running. ההרצה שביקשתם להתחיל או להמשיך עדיין רצה, והשדה executionId מזהה אותה. במקום להתחיל אותה שוב, בדקו את המצב שלה עם client.executions.get(executionId). המתודה client.workflows.run() זורקת את השגיאה הזו כשהרצה של התהליך כבר בעיצומה. המתודה client.apps.resume() זורקת אותה כשניסיון חוזר של ההרצה ממתין.
המחלקה הזו נבחרת כששגיאת ה-409 כוללת executionId. שגיאת 409 שלא מציינת אף הרצה נשארת NodaroError רגילה.
AppRunVersionChangedError
HTTP 409 עם הקוד app_run_version_changed. ניסיון חוזר של הרצת אפליקציה שנכשלה, עם client.apps.resume(), נדחה, כי האפליקציה נמצאת בגרסה אחרת מזו שההרצה הריצה. שום דבר לא נכתב, ולא נגבו קרדיטים.
- השדה
runVersion: הגרסה שההרצה הריצה. - השדה
appVersion: הגרסה שאתם נמצאים בה, כלומר ה-versionששלחתם, או, אם לא שלחתם, הגרסה האחרונה של האפליקציה.
כשהתשובה לא כוללת אותם, שני השדות הם undefined. כדי להריץ את הגרסה הנוכחית של האפליקציה, התחילו את ההרצה מחדש עם client.apps.run(). כדי להמשיך בגרסה של ההרצה עצמה, קראו שוב ל-resume עם { version: err.runVersion }.
מיקומים ואובייקטים משתמשים בקוד התנגשות משלהם, concurrent_modification, שמגיע כ-NodaroError רגילה. טפלו בו באותה דרך: טענו את הפריט מחדש, מזגו ונסו שוב.
אצוות של Studio
שלוש המחלקות האלה שייכות למתודות של הפקות Studio.
StudioOpError: אצווה של פעולות נדחתה, והשדהopIndexהוא המיקום של הפעולה שגרמה לכך, כשהספירה מתחילה מ-0. שום דבר מהאצווה לא נכתב. תקנו את הפעולה הזו ושלחו שוב את כל האצווה.StudioPreviewUnavailable: ביקשתם תצוגה מקדימה עםdryRun: true, והפריסה הזו לא יכולה לתת אותה. האצווה שלכם לא נשלחה. אמרו למשתמש שתצוגה מקדימה לא זמינה, ואל תחילו את האצווה בלי לשאול אותו.StudioPreviewAppliedError: ביקשתם תצוגה מקדימה, והאצווה הוחלה בכל זאת. התייחסו ל-applied.productionול-applied.versionכמצב הנוכחי. אל תשלחו את האצווה שוב. כש-appliedהואundefined, טענו את ההפקה מחדש לפני שאתם מחליטים משהו.
קודים שעשויים להגיע ב-NodaroError
הקודים האלה מגיעים ב-NodaroError רגילה. כדי לטפל בהם, השוו את err.code.
| סטטוס | קוד | איפה | משמעות |
|---|---|---|---|
| 400 | validation_error | מתודות רבות | שדה חסר או לא תקין. השדה message מציין איזה שדה. |
| 400 | no_valid_inputs | client.reduce.run() | כל הקלטים היו ריקים. |
| 400 | invalid_edl | client.edit.applyEdl() | רשימת העריכה לא עברה את בדיקת התקינות. |
| 400 | limit_reached | client.developerApps.create() | כבר הגעתם למספר המרבי של יישומי מפתחים. |
| 400 | locked_field | client.apps.run() | דריסה ניסתה לשנות יעד, כגון כתובת Webhook. |
| 409 | name_taken | דמויות, ארגונים | השם או ה-slug כבר תפוסים. |
| 409 | concurrent_modification | מיקומים, אובייקטים | הפריט השתנה מאז שטענתם אותו. |
| 410 | voice_cloning_retired | client.voices.createClone() | שכפול קול כבר לא מוצע. במקום זאת, עצבו קול. |
| 400 | quote_unsupported | client.nodes.quote() | הפלטפורמה לא יכולה לתת אומדן מחיר לסוג הרכיב הזה. ההודעה מפרטת את הסוגים שאפשר לקבל עליהם אומדן מחיר. |
| 400, 502 | advanced_mode_unavailable | client.llm.structured() | הספק של המודל עצמו לא יכול לקבל כרגע בקשות במצב מתקדם. כבו את המצב המתקדם כדי להריץ את המודל. |
| 409 | job_cancelled | בקשות LLM שמחויבות לפי השימוש, כגון client.llm.structured() | המשימה בוטלה אחרי שהקרדיטים שלה שוריינו, אבל לפני שהקריאה שלה נשלחה. לא נגבים קרדיטים. אל תנסו אותה שוב כמו שהיא: המשימה בוטלה בכוונה. |
| 503 | job_start_failed | בקשות LLM שמחויבות לפי השימוש | השרת לא הצליח לרשום שהקריאה מתחילה, ולכן הוא לא שלח אותה. לא נגבים קרדיטים. נסו שוב. |
| 503 | provider_unavailable | client.llm.structuredJob() | המופע לא יכול להריץ את המודל הזה. אל תנסו שוב. |
| 503 | feature_disabled | client.copilot | היכולת כבויה בפריסה הזו. |
| 503 | nodaro_connection_required | client.edit.editPlan() | התקנה באירוח עצמי צריכה לשם כך חיבור ל-Nodaro Cloud. |
כל דף במדריך מפרט את הקודים של המתודות שלו. דף ה-API שגיאות מפרט כל קוד שה-API יכול לשלוח.
ניסיון חוזר בבטחה
- נסו שוב בקשות קריאה בלי חשש. ל-
getאו ל-listאין תופעות לוואי. - אל תחזרו על בקשה בתשלום בלי לבדוק. ייתכן שבקשה שחרגה מפסק הזמן כבר התחילה הרצה. לפני שאתם מנסים שוב יצירה, העבירו מפתח אידמפוטנטיות: המתודות
client.nodes.run(type, params, { idempotencyKey })ו-runAndWaitמקבלות מפתח כזה. כשאתם מנסים שוב את אותה בקשה, שלחו שוב את אותו מפתח, והפלטפורמה תחזיר את ההרצה הראשונה במקום להתחיל הרצה שנייה ולגבות עליה קרדיטים. - Studio ו-Recast משתמשים באסימוני ניסיון חוזר משלהם: הפרמטר
clientRequestIdבמתודות של Studio והפרמטרrequestIdב-client.recast.rescore(). - נסו שוב אחרי תשובות 5xx, עם הפסקה. פונקציית
fetchמשלכם ב-createClientהיא מקום טוב ללוגיקה הזו.
throwFromResponse(status, body)
throwFromResponse(status: number, body: {
error?: { code?: string; message?: string; [key: string]: unknown }
}): neverממפה סטטוס HTTP וגוף שגיאה של Nodaro למחלקת השגיאה המתאימה, וזורקת אותה. ה-SDK משתמש בה בכל תגובה, והיא מיוצאת בשביל מימושי תעבורה משלכם שקוראים ל-API בלי הלקוח.
מאפיין
סוג
import { throwFromResponse } from "@nodaro/sdk"
throwFromResponse(403, {
error: { code: "insufficient_scope", message: "Missing scope", missingScope: "workflows:execute" },
})
// throws a ForbiddenError whose missingScope is "workflows:execute"רוב הנתיבים עונים עם המעטפת { error: { code, message } }. כמה נתיבים ישנים יותר עונים במבנים אחרים, וה-SDK מפענח גם אותם, כך שגם בשגיאות שלהם יש code ו-message אמיתיים:
| גוף | code | message |
|---|---|---|
{ error: "<code>", message? }, למשל מאימון דמויות | המחרוזת | message, או הקוד כשאין message |
{ error: "<code>", error_description }, מ-OAuth | המחרוזת | error_description |
{ message, issues: [...] }, תשובה על קלט לא תקין עם HTTP 400 | validation_error | message |
{ statusCode, error: "<reason phrase>", message }, למשל נתיב שלא קיים בשרת | internal_error | message |
ב-HTTP 500 ומעלה, ה-SDK לוקח מהמבנים האלה רק את הקוד, אף פעם לא את הטקסט. השדה message של שגיאה כזו הוא הקוד שלה, או "Request failed" (הבקשה נכשלה). השדה message של המעטפת עצמה נלקח בכל סטטוס.
מחלקת השגיאה עדיין נקבעת לפי הסטטוס: שגיאת 404 היא NotFoundError, לא משנה מה כתוב בגוף. כשאין בגוף טקסט קריא, נשארת ההודעה שהמחלקה מגדירה כברירת מחדל, כגון "Not found" (לא נמצא). המחלקה InsufficientCreditsError קוראת את required ואת available מהמעטפת, או את השדות required ו-balance שהשרת שולח לצידה. במכסה לכל משתמש, הערך של available נלקח מ-remaining.
שאלות נפוצות
איך תופסים שגיאות של ה-API של Nodaro ב-TypeScript?
עטפו את הקריאה ב-try/catch ובדקו את השגיאה עם instanceof, מהמחלקה הספציפית ביותר ועד NodaroError בסוף. כל המחלקות מיוצאות מ-@nodaro/sdk.
מה קורה כשאין בחשבון מספיק קרדיטים?
הקריאה זורקת InsufficientCreditsError עם סטטוס HTTP 402, לפני שעבודה כלשהי מתחילה. השדות required ו-available של השגיאה מראים כמה קרדיטים ההרצה צריכה וכמה קרדיטים יש בחשבון.
האם שגיאת JobTimeoutError מבטלת את המשימה?
לא. המשימה ממשיכה לרוץ, ובדרך כלל גם מסתיימת. בדקו אותה מאוחר יותר עם client.jobs.get(jobId), או הגדילו את maxMs למודלים איטיים.
האם כדאי לנסות שוב אחרי שגיאת RateLimitedError?
כן, אחרי הפסקה. המתינו כמה שניות, הכפילו את זמן ההמתנה אחרי כל תשובת 429 חדשה, והפסיקו אחרי כמה ניסיונות.
למה שגיאת 403 לא מציינת את קוד הסיבה המדויק?
רוב תשובות ה-403 מגיעות כ-ForbiddenError עם הקוד forbidden. את הסיבה קוראים ב-message, ואת ההרשאה החסרה ב-missingScope, כשחסרה הרשאת OAuth. מודל שנדחה הוא היוצא מן הכלל: השגיאה עליו מגיעה כ-ModelUnavailableError, עם קוד משלה.
דפים קשורים
SDK ל-TypeScript
משימות והרצות
הרצת רכיבים
שגיאות
מגבלות קצב
עודכן לאחרונה