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:
- Beim Absenden.
POST /v1/generationsantwortet mit einem HTTP-Fehlerstatus und einem Body wie{"error": {"code": "...", "message": "..."}}. Es wurde nichts gestartet und nichts berechnet. - Während der Ausführung. Das Absenden war mit
202erfolgreich, aber der Job endet später mitstatus: "failed". Er enthälterrormit einemcode, einemmessage, den Sie der anfragenden Person anzeigen können, undretryable.
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
| Status | Code | Bedeutung | Erneut versuchen? |
|---|---|---|---|
| 400 | invalid_request | Der Body ist kein JSON, es fehlt model oder input, oder er enthält ein Feld, das die API nicht kennt. | Nein. Body korrigieren. |
| 401 | unauthorized | Der API-Schlüssel fehlt oder ist falsch. | Nein. Schlüssel prüfen. |
| 402 | insufficient_credits | Das Guthaben deckt den für den Job reservierten Preis nicht. | Nach einer Aufladung. |
| 403 | account_disabled, generation_not_enabled | Das Konto ist pausiert, oder der Schlüssel kann Preise abrufen, aber nicht generieren. | Nein. Support kontaktieren. |
| 404 | not_found | Auf Ihrem Konto gibt es keine Generierung mit dieser ID. | Nein. |
| 409 | idempotency_conflict | Der Idempotency-Key wurde bereits mit einem anderen Body verwendet. | Mit einem neuen Schlüssel. |
| 409 | not_ready | Sie haben die Datei angefordert, bevor der Job erfolgreich abgeschlossen war. | Ja, sobald er erfolgreich abgeschlossen ist. |
| 413 | body_too_large | Der JSON-Body ist größer als 1 MB. Laden Sie Dateien hoch und senden Sie stattdessen Links. | Nein. Body verkleinern. |
| 422 | invalid_input | Ein Wert, den das Modell nicht akzeptiert, etwa eine Länge oder Größe, die es nicht anbietet. Die Meldung nennt, welcher. | Nein. Wert ändern. |
| 422 | max_cost_exceeded | Jede Route kostet mehr als Ihr max_cost_usd. | Nein. Obergrenze erhöhen oder Einstellungen senken. |
| 422 | model_not_available | Kein Modell mit dieser ID. | Nein. ID prüfen. |
| 429 | rate_limited | Zu viele Anfragen in derselben Sekunde von einem Konto. | Ja, nach Retry-After. |
| 429 | concurrency_limit | Das Konto hat bereits die maximale Anzahl gleichzeitig laufender Jobs erreicht. | Ja, sobald einer abgeschlossen ist. |
| 500 | server_error | Auf unserer Seite ist etwas schiefgelaufen. | Ja, mit demselben Idempotency-Key. |
| 503 | busy | Kurzzeitige Last. | Ja, nach Retry-After, mit demselben Schlüssel. |
| 503 | model_unavailable | Derzeit 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
| error.code | retryable | Was passiert ist |
|---|---|---|
content_policy | no | Das 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_input | no | Eine Referenz konnte nicht gelesen werden, oder das Modell hat einen Wert abgelehnt. Die Meldung nennt, welchen. |
model_declined | no | Das Modell hat in Worten geantwortet, statt das Bild oder Video zu erzeugen. Beschreiben Sie im Prompt das Ergebnis selbst. |
reference_changed | no | Eine Referenzdatei hat sich nach der Prüfung geändert. Senden Sie sie erneut. |
max_cost_exceeded | no | Die einzige Route, die den Job ausführen kann, kostet mehr als Ihre Obergrenze. |
model_busy | yes | Alle Routen waren ausgelastet. Versuchen Sie es in einer Minute erneut. |
model_unavailable | yes | Derzeit konnte keine Route den Job übernehmen. |
timeout | yes | Keine Route hat rechtzeitig ein Ergebnis geliefert, oder Ihr max_wait_s ist abgelaufen. |
all_routes_failed | yes | Auf 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
503oder einer abgebrochenen Verbindung erneut gesendet, verwendet es denselbenIdempotency-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.
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/modelsund die Modellseite listen für jedes Modell Größen, Längen und Referenzlimits auf. Ein Wert außerhalb davon wird sofort mit422 invalid_inputabgelehnt. - Laden Sie Dateien hoch, statt sie einzubetten.
POST /v1/uploadsnimmt 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/balancevor einem großen Batch erspart eine Serie von402-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.