aisplice

Wenn etwas schiefgeht

Fehler nachschlagen

#Fehler einfügen

Lesen Sie Fehler in dieser Reihenfolge: HTTP-Status, dann error.type, dann error.code. Der Status ist immer aussagekräftig; type sagt Ihnen, wer den Aufruf abgelehnt hat; code ist nur bei Fehlern stabil, die das Gateway selbst erzeugt.

#Wie Sie verzweigen

  1. 1

    Nach dem Status verzweigen

    402 heißt aufladen, 403 heißt Schlüsselberechtigungen, 429 heißt warten, 5xx heißt erneut versuchen. Diese Ebene lügt nie und ändert sich nie.

  2. 2

    error.type prüfen

    xiaoxiang_error stammt von uns. Alles andere — openai_error, claude_error, gemini_error — ist der eigene Body des Anbieters, unverändert weitergeleitet.

  3. 3

    Dann error.code lesen

    Verzweigen Sie nur bei xiaoxiang_error nach code. Upstream-Codes gehören dem Anbieter und können sich ohne Ankündigung ändern.

Nicht jeder Fehler hat einen JSON-Body

Ablehnungen durch das Ratenlimit und zu große Bodys brechen mit einer reinen Statuszeile ab. Ein Parser, der annimmt, dass response.json() immer gelingt, wirft im Fehlerpfad eine Exception, statt den Fehler zu behandeln.
Fehlerstrukturen

Fünf Formen erreichen Ihren Client. Behandeln Sie alle fünf — die letzten drei sind diejenigen, die Integrationen meist übersehen.

Gateway-Fehler

Das Gateway selbst hat den Aufruf abgelehnt — Authentifizierung, Kontingent, Routing, Anfrageformat.

http
{
  "error": {
    "message": "insufficient account balance, please top up to continue (request id: 20260910...)",
    "type": "xiaoxiang_error",
    "code": "insufficient_user_quota"
  }
}

Upstream-Fehler, durchgereicht

Der Anbieter hat mit einem eigenen Fehler geantwortet. Der Body wird unverändert weitergeleitet, type und code stammen also vom Anbieter.

http
{
  "error": {
    "message": "This model's maximum context length is 128000 tokens.",
    "type": "invalid_request_error",
    "code": "context_length_exceeded"
  }
}

Ablehnung durch Vorprüfung

Idempotenz und einige weitere Vorprüfungen antworten, bevor das Relay-Envelope erzeugt wird. Flache Struktur, code in Großbuchstaben.

http
{
  "code": "IDEMPOTENCY_IN_PROGRESS",
  "error": "a request with this Idempotency-Key is still processing"
}

Ablehnung eines asynchronen Tasks

Jeder Task-Endpunkt — Video, Bild-Task, Musik, 3D — meldet Fehler in seiner eigenen flachen Struktur. Hier gibt es kein verschachteltes error-Objekt, ein für /v1/chat/completions geschriebener Parser liest also null.

http
{
  "code": "task_not_exist",
  "message": "task does not exist",
  "data": null
}

Nur Status, leerer Body

Ablehnungen durch das Ratenlimit und zu große Anfrage-Bodys brechen mit einem reinen Statuscode ab.

http
HTTP/1.1 429 Too Many Requests
Retry-After: 20
Content-Length: 0
Antwort-Header

Protokollieren Sie die Anfrage-ID bei jeder Antwort, nicht nur bei Fehlern. Anhand dieser Kennung verfolgt der Support einen Aufruf nach, und sie macht den Unterschied zwischen einer Antwort in fünf Minuten und einem Tag Rätselraten.

HeaderGesendet, wennWas Sie damit tun
X-Oneapi-Request-IdJede Antwort, ob Erfolg oder Fehler.Protokollieren Sie sie neben Ihrer eigenen Trace-ID. Der Support bearbeitet Tickets anhand dieses Werts, und dieselbe ID wird an Fehlermeldungen des Gateways angehängt.
Retry-AfterBei 429 sowie bei 409, solange ein Idempotency-Key noch verarbeitet wird.Warten Sie mindestens so viele Sekunden. Dies ist der einzige Backoff-Hinweis, den das Gateway sendet.
X-Idempotent-ReplayedBei einem wiederholten Idempotency-Key wird eine gespeicherte Antwort erneut ausgeliefert.true bedeutet: Es wurde nichts neu ausgeführt und nichts erneut berechnet — behandeln Sie den Body als das ursprüngliche Ergebnis.
X-Idempotency-SealedDie ursprüngliche Antwort kann nicht sicher erneut ausgeliefert werden (zum Beispiel ein Stream oder ein zu großer Body).Versuchen Sie es mit diesem Schlüssel nicht erneut. Gleichen Sie stattdessen über den Task-Endpunkt oder Ihre eigenen Aufzeichnungen ab.
log-the-request-id.ts
const response = await fetch(url, init);
const requestId = response.headers.get("X-Oneapi-Request-Id");

if (!response.ok) {
  // Bodies are absent on 429 and 413 — never assume JSON here.
  const detail = await response.text();
  logger.error({ status: response.status, requestId, detail });
  throw new GatewayError(response.status, requestId, detail);
}

#Fehlercode-Tabelle

Fehler, die das Gateway selbst erzeugt, immer mit type "xiaoxiang_error". Zwei Zeilen haben beide den Status 429 und bedeuten Gegensätzliches — lesen Sie den code, bevor Sie Backoff anwenden.

HTTPCodeBedeutungWas tunWiederholen?
401keineFehlendes, fehlerhaftes, gelöschtes oder deaktiviertes Bearer-Token. Diese Ebene setzt keinen code — werten Sie den Status aus.Prüfen Sie den Authorization-Header und den Schlüsselstatus unter Konsole → API-Schlüssel.nein
401signature_requiredFür den Schlüssel ist Anfragesignierung aktiviert, und der Anfrage fehlt X-Timestamp, X-Nonce oder X-Signature.Signieren Sie jede Anfrage mit diesem Schlüssel (Authentifizierung & Schlüssel → Anfragesignierung), oder deaktivieren Sie die Signierung für den Schlüssel.nein
401signature_expiredX-Timestamp ist kein 10-stelliger Unix-Sekundenwert oder weicht mehr als 5 Minuten von der Serverzeit ab. Die Antwort enthält X-Server-Timestamp.Korrigieren Sie die Client-Uhr um die Differenz zu X-Server-Timestamp und signieren Sie erneut mit einer neuen Nonce.ja
401signature_invalidX-Signature passt nicht zum Signatur-Secret des Schlüssels, oder X-Nonce ist fehlerhaft.Signieren Sie Zeitstempel, Nonce, Methode und Pfad (ohne Query-String), durch Zeilenumbrüche verbunden, mit dem aktuellen Secret aus Konsole → API-Schlüssel.nein
401signature_replayedDiese X-Nonce wurde mit diesem Schlüssel in den letzten 10 Minuten bereits verwendet.Erzeugen Sie für jede Anfrage eine neue zufällige Nonce, auch bei Wiederholungen.ja
403access_deniedDie IP des Aufrufers liegt außerhalb der IP-Allowlist des Schlüssels.Fügen Sie die ausgehende Adresse unter Konsole → API-Schlüssel hinzu oder entfernen Sie die Allowlist bei Schlüsseln ohne feste IP.nein
403keineKonto gesperrt, oder der Schlüssel darf dieses Modell bzw. diesen Kanal nicht nutzen.Prüfen Sie zuerst die Modell-Allowlist des Schlüssels; ist sie unbeschränkt, eröffnen Sie ein Ticket — dann ist das Konto selbst gesperrt.nein
400unsupported_endpointDas Modell existiert, bedient diesen Pfad aber nicht. Die Meldung listet die Endpunkte auf, die es bedient.Verlegen Sie den Aufruf auf einen der aufgeführten Endpunkte — Bild-Task-Modelle antworten nicht auf /v1/chat/completions.nein
400read_request_body_failedDer Anfrage-Body konnte nicht gelesen werden — abgeschnittener Upload, falscher Content-Type oder ein vorzeitig beendeter Stream.Senden Sie einen vollständigen Body mit passendem Content-Type. Dieselbe fehlerhafte Anfrage scheitert beim erneuten Senden auf dieselbe Weise.nein
402insufficient_user_quotaDas Wallet-Guthaben deckt den für diesen Aufruf vorab reservierten Betrag nicht.Laden Sie unter Konsole → Wallet auf und versuchen Sie es dann erneut.nein
429insufficient_user_quotaDas tägliche Ausgabenlimit des Kontos ist erreicht. Gleicher Status wie bei Drosselung, gegenteilige Bedeutung — Backoff hilft hier nicht.Erhöhen oder entfernen Sie das Limit in den Kontoeinstellungen, oder machen Sie morgen weiter. Werten Sie den code aus, nicht nur 429.nein
429keineRPM/RPD-Drosselung pro Schlüssel oder eine Parallelitätssperre. Der Body ist leer; Retry-After enthält die Wartezeit.Warten Sie Retry-After Sekunden ab und versuchen Sie es dann mit exponentiellem Backoff und Jitter erneut.ja
413read_request_body_failedDer Anfrage-Body überschreitet die zulässige Größe. Das Limit auf Transportebene bricht mit leerem Body ab.Verkleinern Sie den Payload — laden Sie Dateien über /v1/media/upload-policy hoch und senden Sie die URL statt Base64.nein
422invalid_requestKein Kanal unterstützt diesen Medienmodus für das Modell — zum Beispiel Bild-zu-Video auf einer Route, die nur Text-zu-Video kann.Prüfen Sie die unterstützten Modi auf der Modellkarte und wechseln Sie Modell oder Modus.nein
503model_not_foundUnbekannter Modellname, oder derzeit bedient ihn kein funktionsfähiger Kanal. Beachten Sie den Status: Ein unbekanntes Modell ergibt 503, nicht 404.Prüfen Sie den Namen anhand von /v1/models und versuchen Sie es erneut — das Failover findet beim nächsten Versuch meist einen funktionsfähigen Kanal.ja
500sensitive_words_detectedDer Prompt wurde vom Inhaltsfilter abgefangen, bevor er das Gateway verlassen hat.Ändern Sie den Prompt. Derselbe Text scheitert bei jedem Versuch.nein
500count_token_failedDas Gateway konnte die Tokens für die Preisberechnung nicht schätzen, meist wegen eines fehlerhaften messages-Arrays.Validieren Sie das messages-Array; ist es korrekt aufgebaut, versuchen Sie es erneut und eröffnen Sie ein Ticket mit der Anfrage-ID.ja
500invalid_requestDie Anfrage ließ sich nicht in ein Format parsen, das dieser Endpunkt akzeptiert. Beachten Sie den Status — ein Body, den das Gateway nicht lesen kann, wird als 500 gemeldet, nicht als 400.Validieren Sie das JSON vor dem erneuten Versuch anhand der Endpunkt-Referenz.nein
502do_request_failedDer Anbieter war nicht erreichbar oder lieferte einen Fehler, den das Gateway auch per Failover nicht beheben konnte.Mit Backoff erneut versuchen — der nächste Versuch landet meist auf einem anderen Kanal.ja
504do_request_failedDer Anbieter hat nicht innerhalb der Frist des Gateways geantwortet.Mit Backoff erneut versuchen; lange Prompts und ausgelastete Anbieter führen häufiger zu Timeouts.ja
499do_request_failedIhr Client hat die Verbindung geschlossen, bevor die Antwort eintraf — meist hat Ihr eigenes HTTP-Timeout mitten im Stream gegriffen.Erhöhen Sie das Lese-Timeout des Clients. Lange Generierungen brauchen Minuten, nicht den Standardwert der meisten HTTP-Bibliotheken.nein
Fehler der Idempotenzprüfung

Diese stammen von der Replay-Prüfung vor dem Relay und nutzen daher die flache Struktur {code, error} mit code in Großbuchstaben statt der OpenAI-Fehlerstruktur.

HTTPCodeBedeutungWas tunWiederholen?
400IDEMPOTENCY_STREAM_UNSUPPORTEDIdempotency-Key wurde bei einer Streaming-Anfrage gesendet.Lassen Sie den Header bei Streaming-Aufrufen weg, oder setzen Sie stream:false, wenn Sie Replay-Schutz brauchen.nein
400IDEMPOTENCY_BODY_UNREADABLEDer Body konnte für das Idempotenz-Register nicht gehasht werden.Senden Sie einen normalen JSON- oder Multipart-Body — Chunked-Bodys, die sich nicht puffern lassen, werden abgelehnt.nein
409IDEMPOTENCY_PAYLOAD_CONFLICTDieser Schlüssel wurde bereits mit einem anderen Body, Pfad oder Query verwendet.Erzeugen Sie einen neuen Schlüssel. Ein Schlüssel kennzeichnet genau eine Anfrage, nicht eine ganze Wiederholungsschleife.nein
409IDEMPOTENCY_IN_PROGRESSDie erste Anfrage mit diesem Schlüssel läuft noch.Warten Sie Retry-After (2 s) ab und versuchen Sie es mit demselben Schlüssel erneut — Sie erhalten die ursprüngliche Antwort.ja
409IDEMPOTENCY_RESULT_UNREPLAYABLEDie ursprüngliche Anfrage ist abgeschlossen, ihre Antwort wurde jedoch versiegelt und kann nicht erneut ausgeliefert werden.Nicht blind erneut senden. Gleichen Sie zuerst über den Task-Endpunkt oder Ihre eigenen Aufzeichnungen ab.nein
503IDEMPOTENCY_UNAVAILABLEDas Idempotenz-Register ist nicht verfügbar, daher blockiert die Prüfung lieber, statt eine doppelte Belastung zu riskieren.Mit Backoff erneut versuchen — die Anfrage wurde nicht ausgeführt.ja

So funktionieren Idempotenzschlüssel →

Fehler asynchroner Tasks

Video-, Bild-Task-, Musik- und 3D-Endpunkte antworten mit ihrer eigenen flachen Struktur — {code, message, data} — beim Einreichen, Abfragen und Abbrechen gleichermaßen. Eine Eigenheit, die Sie einplanen sollten: Das Abfragen einer unbekannten Task-ID ergibt 400, das Abbrechen 404.

HTTPCodeBedeutungWas tunWiederholen?
400task_not_existAbfragen oder Remixen einer Task-ID, die nicht existiert oder zu einem anderen Konto gehört. Beachten Sie den Status — das Abfragen eines unbekannten Tasks ergibt 400, das Abbrechen dagegen 404.Speichern Sie task_id beim Einreichen und fragen Sie mit genau diesem Wert ab.nein
400invalid_requestEin Pflichtfeld fehlt — prompt bei einem Remix, task_id bei einem Abruf.Korrigieren Sie Body oder Pfad, bevor Sie es erneut versuchen.nein
400task_channel_disableEin Folge-Task (Remix, Verlängerung) ist an den Kanal des ursprünglichen Tasks gebunden, und dieser Kanal ist jetzt deaktiviert.Reichen Sie einen neuen Task ein, statt vom alten abzuleiten.nein
400invalid_source_taskDer Quell-Task hat den falschen Typ für diese Operation — zum Beispiel eine Video-ID, die an eine 3D-Fortsetzung übergeben wird.Prüfen Sie, ob die Quell-ID aus derselben Fähigkeitsfamilie stammt.nein
404task_not_existAbbrechen einer Task-ID, die nicht existiert oder nicht Ihnen gehört.Nichts abzubrechen — behandeln Sie den Task als bereits entfernt.nein
409task_not_cancellableDer Task hat bereits einen Endzustand erreicht, es gibt also nichts abzubrechen.Fragen Sie noch einmal ab und verwenden Sie das Ergebnis, das Sie bereits bezahlt haben.nein
501task_cancel_not_supportedDer Anbieter hinter diesem Task bietet keine API zum Abbrechen. Die meisten tun das nicht — Abbrechen ist die Ausnahme, nicht die Regel.Lassen Sie den Task zu Ende laufen. Gestalten Sie die UI so, dass Abbrechen ein Versuch ist, keine Garantie.nein
502cancel_task_failedDer Anbieter war beim Abbrechen nicht erreichbar. Der Task ist unverändert.Einmal erneut versuchen, sonst den Task zu Ende laufen lassen.ja

Lebenszyklus asynchroner Tasks →

Immer noch nicht gelöst?

Senden Sie uns die Anfrage-ID oder die Fehlermeldung, und wir sehen uns das an.