So funktioniert's

Fehlercodes der KI-Video-API: Was sie bedeuten und wann Sie es erneut versuchen sollten

Jobs zur Videogenerierung schlagen häufiger fehl als gewöhnliche API-Aufrufe: Modelle sind ausgelastet, lehnen Prompts ab oder laufen in ein Timeout. Dieser Leitfaden listet jeden möglichen Fehler auf, welche sich für einen erneuten Versuch lohnen und wie Sie sicher wiederholen.

Zwei Stellen, an denen ein Fehler auftreten kann

Ein Video- oder Bild-Job kann an zwei Punkten scheitern, und Ihr Code muss beide behandeln:

  1. Beim Absenden. POST /v1/generations antwortet mit einem HTTP-Fehlerstatus und einem Body wie {"error": {"code": "...", "message": "..."}}. Es wurde nichts gestartet und nichts berechnet.
  2. Während der Ausführung. Das Absenden war mit 202 erfolgreich, aber der Job endet später mit status: "failed". Er enthält error mit einem code, einem message, den Sie der anfragenden Person anzeigen können, und retryable.

Ein fehlgeschlagener Job wird bei keinem Modell berechnet. Der Preis wird beim Absenden von Ihrem Guthaben reserviert und freigegeben, wenn der Job fehlschlägt.

HTTP-Fehler beim Absenden

HTTP-Fehlercodes des Generations-Endpunkts
StatusCodeBedeutungErneut versuchen?
400invalid_requestDer Body ist kein JSON, es fehlt model oder input, oder er enthält ein Feld, das die API nicht kennt.Nein. Body korrigieren.
401unauthorizedDer API-Schlüssel fehlt oder ist falsch.Nein. Schlüssel prüfen.
402insufficient_creditsDas Guthaben deckt den für den Job reservierten Preis nicht.Nach einer Aufladung.
403account_disabled, generation_not_enabledDas Konto ist pausiert, oder der Schlüssel kann Preise abrufen, aber nicht generieren.Nein. Support kontaktieren.
404not_foundAuf Ihrem Konto gibt es keine Generierung mit dieser ID.Nein.
409idempotency_conflictDer Idempotency-Key wurde bereits mit einem anderen Body verwendet.Mit einem neuen Schlüssel.
409not_readySie haben die Datei angefordert, bevor der Job erfolgreich abgeschlossen war.Ja, sobald er erfolgreich abgeschlossen ist.
413body_too_largeDer JSON-Body ist größer als 1 MB. Laden Sie Dateien hoch und senden Sie stattdessen Links.Nein. Body verkleinern.
422invalid_inputEin Wert, den das Modell nicht akzeptiert, etwa eine Länge oder Größe, die es nicht anbietet. Die Meldung nennt, welcher.Nein. Wert ändern.
422max_cost_exceededJede Route kostet mehr als Ihr max_cost_usd.Nein. Obergrenze erhöhen oder Einstellungen senken.
422model_not_availableKein Modell mit dieser ID.Nein. ID prüfen.
429rate_limitedZu viele Anfragen in derselben Sekunde von einem Konto.Ja, nach Retry-After.
429concurrency_limitDas Konto hat bereits die maximale Anzahl gleichzeitig laufender Jobs erreicht.Ja, sobald einer abgeschlossen ist.
500server_errorAuf unserer Seite ist etwas schiefgelaufen.Ja, mit demselben Idempotency-Key.
503busyKurzzeitige Last.Ja, nach Retry-After, mit demselben Schlüssel.
503model_unavailableDerzeit ist keine Route für dieses Modell verfügbar.Ja, in Kürze.

Faustregel: 429, 500 und 503 lohnen sich mit Backoff erneut zu versuchen; alles im Bereich 4xx außer 429 bedeutet, dass die Anfrage selbst geändert werden muss.

Warum ein Job nach dem Start fehlschlägt

Fehlercodes bei einer fehlgeschlagenen Generierung
error.coderetryableWas passiert ist
content_policynoDas Modell hat den Prompt oder die Medien abgelehnt oder sein Ergebnis zurückgehalten. reason nennt den Grund: sexual, minors, copyright, real_person oder other.
invalid_inputnoEine Referenz konnte nicht gelesen werden, oder das Modell hat einen Wert abgelehnt. Die Meldung nennt, welchen.
model_declinednoDas Modell hat in Worten geantwortet, statt das Bild oder Video zu erzeugen. Beschreiben Sie im Prompt das Ergebnis selbst.
reference_changednoEine Referenzdatei hat sich nach der Prüfung geändert. Senden Sie sie erneut.
max_cost_exceedednoDie einzige Route, die den Job ausführen kann, kostet mehr als Ihre Obergrenze.
model_busyyesAlle Routen waren ausgelastet. Versuchen Sie es in einer Minute erneut.
model_unavailableyesDerzeit konnte keine Route den Job übernehmen.
timeoutyesKeine Route hat rechtzeitig ein Ergebnis geliefert, oder Ihr max_wait_s ist abgelaufen.
all_routes_failedyesAuf allen Routen ist es aus Gründen auf deren Seite fehlgeschlagen.

Im Hintergrund wechselt ein Job, der auf eine ausgelastete oder defekte Route trifft, selbstständig zur nächsten Route. Wenn Sie also model_busy oder all_routes_failed sehen, wurden bereits alle Routen versucht. Das Feld attempts gibt an, wie viele. Meist genügt es, ein bis zwei Minuten zu warten und es dann erneut zu versuchen.

Ablehnungen wegen Inhalten

content_policy ist der Fehler, auf den man am häufigsten stößt. Die Entscheidung trifft das Modell, nicht die API, und reason nennt die ausgelöste Regel. Häufige Ursachen sind der Name oder das Gesicht einer bekannten Person im Prompt oder in einem Referenzbild (real_person), Marken und bekannte Figuren (copyright) sowie alles, was nach einer minderjährigen Person aussieht. Dieselbe Anfrage erneut zu senden hilft nicht; formulieren Sie den Prompt um oder ändern Sie das Bild. Modelle sind unterschiedlich streng, derselbe Prompt kann bei einem durchgehen und bei einem anderen abgelehnt werden.

Eine Retry-Schleife, die das Richtige tut

Dieser Python-Helfer wiederholt, was sich lohnt, und bricht bei allem anderen ab. Zwei Details sind wichtig:

  • Wird ein Absenden nach einem 503 oder einer abgebrochenen Verbindung erneut gesendet, verwendet es denselben Idempotency-Key, sodass nie ein zweiter, kostenpflichtiger Job gestartet werden kann.
  • Ein neuer Versuch, nachdem ein Job fehlgeschlagen ist, verwendet einen neuen Schlüssel. Derselbe Schlüssel würde nur den fehlgeschlagenen Job zurückgeben.
Python
import os
import time
import uuid

import requests

API = "https://api.revana.si/v1"
AUTH = {"Authorization": f"Bearer {os.environ['REVANA_API_KEY']}"}
RETRY_HTTP = {429, 500, 503}


class GenerationError(Exception):
    pass


def submit(body):
    """POST a job. Retries 429, 500 and 503 with the same Idempotency-Key, so a retry never starts a second job."""
    headers = {**AUTH, "Idempotency-Key": str(uuid.uuid4())}
    for attempt in range(6):
        r = requests.post(f"{API}/generations", headers=headers, json=body, timeout=60)
        if r.ok:
            return r.json()
        if r.status_code in RETRY_HTTP:
            time.sleep(float(r.headers.get("Retry-After", 2 ** attempt)))
            continue
        err = r.json()["error"]  # 400, 401, 402, 403, 409, 413, 422: fix the request, do not retry
        raise GenerationError(f"{r.status_code} {err['code']}: {err['message']}")
    raise GenerationError("still busy after 6 tries")


def wait(job):
    while job["status"] in ("queued", "running"):
        time.sleep(5)
        job = requests.get(f"{API}/generations/{job['id']}", headers=AUTH).json()
    return job


def generate(body, tries=3):
    for n in range(tries):
        job = wait(submit(body))  # each call uses a new key: a failed job is final
        if job["status"] == "succeeded":
            return job
        err = job["error"]
        if not err["retryable"]:
            raise GenerationError(f"{err['code']}: {err['message']}")
        time.sleep(60 * (n + 1))  # model_busy, timeout and the like: wait, then try again
    raise GenerationError(f"gave up after {tries} tries: {err['code']}")


job = generate({
    "model": "seedance-2.0-fast",
    "input": {"prompt": "Waves roll onto black sand at sunset.", "resolution": "480p", "duration": 5},
    "max_cost_usd": 0.3,
})
print(job["output"]["urls"][0], job["cost_usd"])

Der Beispiel-Job ist ein 5 Sekunden langer 480p-Clip mit Seedance 2.0 Fast, der $0.25 kostet, wenn er gelingt, und nichts, wenn er fehlschlägt. Die Obergrenze max_cost_usd verhindert, dass eine falsche Einstellung mehr kostet als erwartet.

Fehler von vornherein vermeiden

  • Lesen Sie die Optionen, bevor Sie senden. GET /v1/models und die Modellseite listen für jedes Modell Größen, Längen und Referenzlimits auf. Ein Wert außerhalb davon wird sofort mit 422 invalid_input abgelehnt.
  • Laden Sie Dateien hoch, statt sie einzubetten. POST /v1/uploads nimmt Bilder bis 30 MB, Clips bis 50 MB und Audio bis 15 MB an und liefert einen Link, der 14 Tage gültig ist. So bleibt der Request-Body klein.
  • Prüfen Sie Ihr Guthaben im Code. GET /v1/balance vor einem großen Batch erspart eine Serie von 402-Fehlern. Credit-Pakete finden Sie auf der Preisseite.

Wie Sie die Kosten erfolgreicher Jobs senken, lesen Sie unter KI-Video-API-Kosten senken. Die vollständige Fehlerreferenz steht in der Dokumentation; holen Sie sich einen API-Schlüssel, um es auszuprobieren.

Häufig gestellte Fragen

Werden mir Kosten berechnet, wenn eine KI-Videogenerierung fehlschlägt?

Nein. Der Preis wird beim Absenden reserviert und freigegeben, sobald der Job fehlschlägt, egal aus welchem Grund.

Welche Fehler sollte ich erneut versuchen?

Beim Absenden: 429, 500 und 503 nach der Wartezeit aus Retry-After erneut versuchen. Bei einem fehlgeschlagenen Job: erneut versuchen, wenn error.retryable true ist: model_busy, model_unavailable, timeout und all_routes_failed.

Was bedeutet content_policy?

Das Modell hat den Prompt oder die Medien abgelehnt oder das Ergebnis zurückgehalten. Das Feld reason nennt die Regel: sexual, minors, copyright, real_person oder other. Ändern Sie die Anfrage, statt sie erneut zu senden.

Wie wiederhole ich eine Anfrage, ohne doppelt zu zahlen?

Senden Sie einen Idempotency-Key-Header und verwenden Sie ihn erneut, wenn Sie nach einem Timeout oder einem 503 noch einmal senden. Sie erhalten dieselbe Generierung zurück, keine zweite.

Was bedeutet 422 invalid_input?

Das Modell akzeptiert einen von Ihnen gesendeten Wert nicht, etwa eine Länge, eine Größe oder die Anzahl der Referenzbilder. Die Meldung nennt das Feld und die zulässigen Werte.

Bauen Sie auf einer API, die Fehlschläge nie berechnet

Ein API-Schlüssel für jedes Video- und Bildmodell, mit automatischem Fallback zwischen Routen. Vorausbezahltes Guthaben ab $10, berechnet nur für erfolgreiche Jobs.