Bei der Moonshot API reicht der Statuscode allein nicht aus. Ein 429 kann eine Überlastung des Clusters, eine Kontingentgrenze des Kontos oder fehlendes Guthaben bedeuten; ein 401 kann an einem falschen Key liegen oder an der Verwechslung von chinesischer und internationaler Site. Der Plattformumzug 2026 und das Auslaufen alter Modelle haben zusätzlich 404-Fehler häufiger gemacht.

Dieser Beitrag geht in der Reihenfolge „erst lokalisieren, dann klassifizieren, dann beheben“ auf fünf Problemklassen ein: 401, 404, 429, zu langen Kontext und Timeouts. Dazu gibt es wiederverwendbaren Retry-Code und eine Checkliste für Support-Tickets. Modelle und Preise richten sich nach den Modellpreisen auf dieser Website.

Hinweis: Moonshot und Kimi sind Marken der jeweiligen Inhaber. Fehlertypen, Limitstufen und Abschalttermine können sich ändern; dieser Beitrag stützt sich auf die offizielle Dokumentation und typische Fälle mit Stand Oktober 2026. Maßgeblich ist die offizielle Dokumentation.

1. Zuerst drei Felder festhalten

Für die Fehlersuche zuerst drei Dinge sammeln: HTTP-Statuscode, error.type und die Request-ID. Moonshot-Fehlerantworten enthalten üblicherweise error.message und error.type; die genauen Felder richten sich nach der aktuellen Antwort der Schnittstelle. Die Request-ID kann im Fehlerkörper, in einem Response-Header oder im Konsolenprotokoll stehen; ihre Position variiert je nach Version, daher nicht von einer einzigen Quelle ausgehen.

Im Log mindestens erfassen: Zeitpunkt (mit Zeitzone), Statuscode, error.type, Modellname, Site der Base URL, ob gestreamt wurde, SDK-Version, Anzahl der Retries, usage und Request-ID. Nie den vollständigen Key protokollieren und keine Prompts mit sensiblen Daten.

Mit diesen drei Angaben lässt sich entscheiden, ob das Problem in der Konfiguration, im Konto oder beim Dienst liegt. Die folgenden Abschnitte gehen die Klassen einzeln durch.

2. 401: erst die Site prüfen, dann den Key

Moonshot unterscheidet eine chinesische und eine internationale Site: Die chinesische Site läuft unter platform.kimi.com mit der Schnittstelle https://api.moonshot.cn/v1, die internationale unter platform.kimi.ai mit https://api.moonshot.ai/v1. Konten, Guthaben und Keys sind vollständig getrennt; ein Key der chinesischen Site an der internationalen Adresse führt zu 401 invalid_authentication_error.

In dieser Reihenfolge prüfen:

  1. Stammt der Key von der Site, zu der die Base URL gehört, und nicht von der anderen Site oder einem anderen Konto?
  2. Wurden Keys der Open Platform und anderer Produktlinien wie Kimi Code vermischt? Sie sind nicht austauschbar.
  3. Lautet der Header Authorization: Bearer <key>, ohne Leerzeichen, Zeilenumbruch oder Anführungszeichen um den Wert?
  4. Wird die Umgebungsvariable tatsächlich geladen? Testweise nur die ersten Zeichen des Keys ausgeben.
  5. Wurde der Key gelöscht oder rotiert, oder wurde die Projektberechtigung entzogen?
  6. Liegen lokal noch alte Proxy-, Umgebungs- oder Routingkonfigurationen, die die Anfrage überschreiben?

invalid_authentication_error deutet meist auf ein Format- oder Site-Problem hin, incorrect_api_key_error auf einen fehlenden oder falschen Key. In beiden Fällen zuerst die Zugangsdaten korrigieren, nicht sofort wiederholen.

3. 404: meist ein eingestelltes Modell, keine verschwundene Schnittstelle

Die 2026 am häufigsten übersehene 404-Ursache ist der Modelllebenszyklus. Die offizielle Modellseite nennt unter anderem:

  • Die gesamte moonshot-v1-Reihe mit moonshot-v1-8k, -32k, -128k, -auto und den Vision-Preview-Versionen wurde am 31. August 2026 eingestellt; empfohlen wird die Migration zu kimi-k3.
  • Die kimi-k2-Reihe mit kimi-k2-0905-preview, kimi-k2-0711-preview, kimi-k2-turbo-preview und der Thinking-Version wurde am 25. Mai 2026 eingestellt.
  • kimi-latest wurde am 28. Januar 2026 eingestellt, kimi-thinking-preview am 11. November 2025.

Weitere häufige 404-Ursachen:

  • Das OpenAI SDK hat keine base_url gesetzt, die Anfrage ging an die Standardadresse von OpenAI und das Modell existiert dort nicht.
  • Der Modellname ist falsch geschrieben, oder das Konto hat keinen Zugriff auf die Stufe.
  • Im Pfad fehlt /v1 oder es ist doppelt vorhanden, oder der Client setzt Base URL und vollständigen Pfad falsch zusammen.
  • Chinesische und internationale Site bieten unterschiedliche Modellnamen an.

Mit demselben Key die Modellliste abrufen und prüfen, was das Konto tatsächlich sieht:

curl "https://api.moonshot.cn/v1/models" \
  -H "Authorization: Bearer $MOONSHOT_API_KEY"

Modelle, die nicht in der Liste stehen, nicht raten. Wenn die Modellliste funktioniert, der Chat-Aufruf aber weiter 404 liefert, vor allem Pfadzusammensetzung und Client-Konfiguration prüfen.

4. 429: drei Typen mit völlig unterschiedlicher Behandlung

429 ist die am leichtesten fehlinterpretierte Klasse. Zuerst error.type ansehen:

error.type Bedeutung Wiederholbar Vorgehen
engine_overloaded_error Cluster überlastet, Kapazität knapp Ja Nach Retry-After zurückweichen, Parallelität senken
rate_limit_reached_error Parallelität, RPM, TPM oder TPD auf Organisationsebene überschritten Teilweise Drosseln, warten, Kontostufe erhöhen
exceeded_current_quota_error Zahlungsrückstand, zu wenig Guthaben, Gutschein abgelaufen Nein Guthaben prüfen und aufladen

Moonshots Limitstufen richten sich nach der kumulierten Aufladung des Kontos und reichen von Tier0 bis Tier5; Aufladegutscheine zählen üblicherweise nicht zur Kumulierung. Die Stufe begrenzt gleichzeitig Parallelität, Anfragen pro Minute, Tokens pro Minute und Tokens pro Tag: Niedrige Stufen erlauben oft nur einstellige Parallelität, hohe Stufen bis zu hundert; RPM reicht von einstelligen Werten bis zu mehreren Hundert, TPM von Hunderttausenden bis Millionen. Tier0 hat zusätzlich eine Tagesgrenze für Tokens; danach muss meist auf den nächsten Tag gewartet werden.

Häufige Fallstricke:

  • Das OpenAI SDK wiederholt 408, 409, 429 und 5xx standardmäßig automatisch, insgesamt bis zu drei Mal. Bei niedriger Stufe kann ein Fehlversuch so zu mehreren Anfragen werden und das RPM schnell aufbrauchen. In Produktion max_retries explizit setzen.
  • Tools wie die Websuche haben eigene QPS-Grenzen, getrennt von RPM und TPM des Chat-Endpunkts; auch dort führt Überschreitung zu 429.
  • Durch 429 abgebrochene Anfragen werden üblicherweise nicht berechnet; ein erfolgreicher Retry wird normal berechnet. Wegen „kostenlos“ nicht unbegrenzt wiederholen.
  • Wenn Limits und Stufe nicht zusammenpassen, zuerst prüfen, ob der Key zu einem anderen Konto gehört.

5. 400: zu langer Kontext und Parameterfehler

Ein zu langer Kontext liefert meist 400 invalid_request_error mit dem Hinweis, dass die Eingabe-Tokens das Limit überschreiten. Entscheidend ist, ob „Eingabe plus Ausgabeobergrenze“ das Modellfenster übersteigt, nicht die Eingabe allein.

Typische Auslöser:

  • Der Verlauf wächst unbegrenzt, mehrstufige Dialoge werden nie gekürzt.
  • Ein ganzes Dokument wird in einen 1M-Kontext gelegt und gleichzeitig eine sehr große Ausgabeobergrenze gesetzt.
  • Der Datei-Endpunkt erhält mehr als 100 MB, eine leere Datei oder einen purpose-Wert außerhalb der erlaubten Liste.
  • Die Ausgabe löst content_filter aus; solche Filter können auch durch die Modellausgabe greifen, nicht nur durch die Eingabe.

Reihenfolge: zuerst Eingabe-Tokens schätzen, dann Platz für die Ausgabe lassen; lange Dokumente abschnittsweise zusammenfassen und Quellen behalten; mehrstufige Dialoge mit einem gleitenden Fenster führen; strukturierte Ausgaben über Tool-Aufrufe erzeugen, um unnötig lange Texte zu vermeiden.

finish_reason=length ist kein Fehler, sondern zeigt an, dass die Ausgabe die Obergrenze erreicht hat. Für längere Ergebnisse abschnittsweise anfragen oder eine Fortsetzungsfunktion nutzen, die Obergrenze aber nicht über den vom Modell erlaubten Wert hinaus anheben.

6. Timeouts, 499 und Streaming

Das Gateway von Moonshot hat für nicht gestreamte Anfragen eine Wartegrenze; die offizielle Dokumentation nennt 504 nach 900 Sekunden. Am häufigsten trifft es lange Textgenerierung, Dokumentenanalyse und Code-Agenten.

In dieser Reihenfolge behandeln:

  1. Von nicht gestreamt auf Streaming umstellen, stream=True setzen, damit die Verbindung laufend Daten liefert.
  2. Den Verbindungs-Timeout kurz halten, den Lese-Timeout auf die längste erwartete Generierungszeit setzen, nicht die SDK-Standardwerte übernehmen.
  3. Prüfen, ob Firmenproxy, Gateway oder lokale Routing-Tools die Verbindung vorzeitig trennen; solche Abbrüche erscheinen oft als 499 client_closed_request.
  4. Die Ausgabeobergrenze zur Steuerung der Länge pro Aufruf nutzen und sehr lange Aufgaben aufteilen.
  5. Beim Streaming die Zeit bis zum ersten Token beobachten; ein plötzlicher Anstieg deutet meist auf Überlastung stromaufwärts oder einen längeren Prompt hin.
  6. Für jeden Timeout Request-ID und Dauer protokollieren, um langsames Modell, langsames Netz und langsamen Proxy zu unterscheiden.

Streaming senkt den Stückpreis nicht, reduziert aber den doppelten Verbrauch durch „bis zum Timeout warten und dann wiederholen“. Den Lese-Timeout nicht vom kurzen Wert für nicht gestreamte Anfragen übernehmen, sonst trennt der Client die Verbindung während einer normalen Generierung selbst.

7. Retry und Backoff richtig schreiben

Retries eignen sich nur für vorübergehende Fehler. 401, 403, 404, Inhaltsfilter und fehlendes Guthaben nicht automatisch wiederholen; 429 zuerst klassifizieren; 5xx darf zurückweichen. Bei Vorgängen mit Nebenwirkungen vorher per Idempotenzschlüssel oder Statusabfrage klären, ob sie bereits ausgeführt wurden.

import random
import time
from openai import OpenAI, APIStatusError, RateLimitError

client = OpenAI(
    api_key="IHR_KEY",
    base_url="https://api.moonshot.cn/v1",
    max_retries=0,  # automatische SDK-Retries deaktivieren
)

RETRYABLE_TYPES = {"engine_overloaded_error", "server_error",
                   "server_unavailable", "client_closed_request"}

def ask(prompt: str, retries: int = 4) -> str:
    for attempt in range(retries):
        try:
            resp = client.chat.completions.create(
                model="kimi-k3",
                messages=[{"role": "user", "content": prompt}],
                max_completion_tokens=1024,
            )
            return resp.choices[0].message.content
        except RateLimitError as exc:
            body = exc.body or {}
            etype = (body.get("error") or {}).get("type", "")
            if etype == "exceeded_current_quota_error":
                raise RuntimeError("Guthaben oder Kontingent reicht nicht, zuerst aufladen")
            if etype == "rate_limit_reached_error":
                raise RuntimeError("Kontolimit erreicht, Parallelitaet senken oder Stufe erhoehen")
            wait = min(2 ** attempt, 20) + random.random()
            print(etype or "overloaded", "warte", round(wait, 1), "Sekunden")
            time.sleep(wait)
        except APIStatusError as exc:
            if exc.status_code in (401, 403, 404):
                raise
            if exc.status_code >= 500:
                time.sleep(min(2 ** attempt, 20) + random.random())
            else:
                raise
    raise RuntimeError("Retry-Kontingent erschoepft")

print(ask("Erlaeutere die Grenzen von Retries"))

Wenn ein Retry-After-Header vorliegt, zuerst danach warten und dann Jitter addieren, damit mehrere Instanzen nicht gleichzeitig erneut anfragen und eine zweite Überlastung erzeugen. Die Retry-Anzahl begrenzen und endgültige Fehler in die Alarmierung schreiben.

8. Was vor einem Support-Ticket vorbereitet sein sollte

  1. Zeitpunkt mit Zeitzone und Jahr, auf die Sekunde genau.
  2. Request-ID, Response-id und usage-Felder.
  3. Modellname, Base URL, Site (chinesisch oder international) und ob gestreamt wurde.
  4. HTTP-Statuscode, error.type und vollständige Fehlermeldung.
  5. SDK- und Client-Version, Retry-Konfiguration, ob ein Proxy oder Gateway beteiligt war.
  6. Eine minimal reproduzierbare Anfrage, idealerweise ein einzelnes curl.
  7. Rechnungs- oder Nutzungsdaten zur Prüfung auf doppelte Abrechnung.
  8. Bereinigte Logs ohne Key, Nutzerdaten und sensible Prompts.

Zuerst mit einem direkten curl reproduzieren, dann die Ergebnisse von Direktverbindung und Gateway getrennt einreichen; das verkürzt die Lokalisierung erheblich.

Häufig gestellte Fragen

Wird bei einem 429-Retry doppelt berechnet?

Durch 429 abgelehnte Anfragen werden üblicherweise nicht berechnet; ein erfolgreicher Retry wird als normale Anfrage berechnet. Problematisch ist eher, dass automatische SDK-Retries eine Geschäftsanfrage in mehrere Anfragen verwandeln und Anfragezahl sowie Kosten gleichzeitig steigen.

Ein Modell lief gestern noch, heute kommt 404 – warum?

Zuerst die Abschaltliste auf der offiziellen Modellseite prüfen. Die moonshot-v1-Reihe wurde am 31. August 2026 eingestellt, kimi-k2 und kimi-latest werden ebenfalls nicht mehr gepflegt; die offizielle Empfehlung ist die Migration zu kimi-k3.

429 meldet fehlendes Guthaben – trotzdem mit Backoff wiederholen?

Nein. exceeded_current_quota_error betrifft Guthaben oder Kontingent; ein Retry stellt nichts wieder her. Zuerst Guthaben, Zahlungsstatus und Gültigkeit der Gutscheine prüfen.

Warum gibt es trotz Streaming noch Timeouts?

Streaming verkürzt die Wartezeit auf das erste Paket, garantiert aber keine dauerhaft offene Verbindung. Idle-Timeout des Proxys, Lese-Timeout, Ausgabeobergrenze und Netzstabilität prüfen; auch eine lange Phase ohne neue Tokens kann Zwischengeräte zum Trennen veranlassen.

Direktverbindung funktioniert, über das Gateway kommt ein Fehler – wer ist verantwortlich?

Mit demselben Key, Modell und derselben Anfrage einmal direkt und einmal über das Gateway testen und Statuscode, error.type, Request-ID und Dauer vergleichen. Scheitert nur das Gateway, vor allem Pfad, Authentifizierung, Timeout und Retry-Konfiguration dort prüfen.

Nächster Schritt

Erstellen Sie zunächst im ZSQH AI Gateway einen Test-Key, üben Sie 401, 404, 429 und Timeouts je einmal durch und hängen Sie dann die Produktionsüberwachung an. Verfügbare Modelle und Abrechnung richten sich nach den Modellpreisen.

Weiterführende Beiträge: