Kode error API video AI: artinya dan kapan harus mencoba ulang
Job generasi video lebih sering gagal dibanding panggilan API biasa: model sedang sibuk, menolak prompt, atau timeout. Panduan ini mencantumkan semua error yang bisa Anda terima, mana yang layak dicoba ulang, dan cara mencoba ulang dengan aman.
Dua tempat error bisa muncul
Job video atau gambar bisa gagal di dua momen, dan kode Anda harus menangani keduanya:
- Saat Anda mengirim.
POST /v1/generationsmenjawab dengan status error HTTP dan body seperti{"error": {"code": "...", "message": "..."}}. Tidak ada yang dimulai dan tidak ada yang ditagih. - Saat job berjalan. Submit berhasil dengan
202, tetapi job kemudian berakhir denganstatus: "failed".error-nya berisicode,messageyang bisa Anda tampilkan kepada orang yang meminta, danretryable.
Job yang gagal tidak pernah ditagih di model mana pun. Harganya ditahan dari saldo Anda saat submit dan dilepas kembali jika job gagal.
Error HTTP saat submit
| Status | Kode | Arti | Coba ulang? |
|---|---|---|---|
| 400 | invalid_request | Body bukan JSON, tidak memiliki model atau input, atau berisi field yang tidak dikenal API. | Tidak. Perbaiki body. |
| 401 | unauthorized | Kunci API tidak ada atau salah. | Tidak. Periksa kuncinya. |
| 402 | insufficient_credits | Saldo tidak cukup untuk harga yang ditahan bagi job ini. | Setelah top-up. |
| 403 | account_disabled, generation_not_enabled | Akun dijeda, atau kunci bisa membaca harga tetapi tidak bisa membuat generasi. | Tidak. Hubungi dukungan. |
| 404 | not_found | Tidak ada generasi dengan id tersebut di akun Anda. | Tidak. |
| 409 | idempotency_conflict | Idempotency-Key sudah dipakai dengan body yang berbeda. | Dengan kunci baru. |
| 409 | not_ready | Anda meminta file sebelum job berhasil. | Ya, setelah berhasil. |
| 413 | body_too_large | Body JSON lebih dari 1 MB. Unggah file dan kirim tautannya. | Tidak. Perkecil body. |
| 422 | invalid_input | Nilai yang tidak diterima model, seperti durasi atau ukuran yang tidak ada dalam daftarnya. Pesan error menyebutkan yang mana. | Tidak. Ubah nilainya. |
| 422 | max_cost_exceeded | Setiap rute lebih mahal daripada max_cost_usd Anda. | Tidak. Naikkan batasnya atau turunkan pengaturannya. |
| 422 | model_not_available | Tidak ada model dengan id tersebut. | Tidak. Periksa id-nya. |
| 429 | rate_limited | Terlalu banyak permintaan dalam detik yang sama dari satu akun. | Ya, setelah Retry-After. |
| 429 | concurrency_limit | Akun sudah mencapai jumlah maksimum job yang berjalan. | Ya, saat salah satu selesai. |
| 500 | server_error | Ada masalah di sisi kami. | Ya, dengan Idempotency-Key yang sama. |
| 503 | busy | Beban sesaat. | Ya, setelah Retry-After, dengan kunci yang sama. |
| 503 | model_unavailable | Saat ini tidak ada rute yang aktif untuk model ini. | Ya, sebentar lagi. |
Aturan praktisnya: 429, 500 dan 503 layak dicoba ulang dengan backoff; semua kode di rentang 4xx kecuali 429 berarti permintaannya sendiri harus diubah.
Mengapa job gagal setelah dimulai
| error.code | retryable | Apa yang terjadi |
|---|---|---|
content_policy | no | Model menolak prompt atau media, atau menahan hasilnya. reason menjelaskan alasannya: sexual, minors, copyright, real_person atau other. |
invalid_input | no | Referensi tidak bisa dibaca, atau model menolak sebuah nilai. Pesan error menyebutkan yang mana. |
model_declined | no | Model menjawab dengan kata-kata, bukan membuat gambar atau video. Deskripsikan hasil yang diinginkan langsung di prompt. |
reference_changed | no | File referensi berubah setelah diperiksa. Kirim ulang. |
max_cost_exceeded | no | Satu-satunya rute yang bisa menjalankannya lebih mahal daripada batas Anda. |
model_busy | yes | Semua rute sedang penuh. Coba lagi dalam semenit. |
model_unavailable | yes | Saat ini tidak ada rute yang bisa menerima job. |
timeout | yes | Tidak ada rute yang mengembalikan hasil tepat waktu, atau max_wait_s Anda sudah lewat. |
all_routes_failed | yes | Semua rute gagal karena masalah di sisinya. |
Di balik layar, job yang menemui rute sibuk atau rusak akan pindah sendiri ke rute berikutnya, jadi saat Anda melihat model_busy atau all_routes_failed, semua rute sudah dicoba. Field attempts menyebutkan jumlahnya. Menunggu satu atau dua menit sebelum mencoba lagi biasanya sudah cukup.
Penolakan konten
content_policy adalah kegagalan yang paling sering dialami. Modellah, bukan API, yang memutuskannya, dan reason memberi tahu aturan mana yang aktif. Penyebab umumnya adalah nama atau wajah orang terkenal di prompt atau gambar referensi (real_person), merek dan karakter terkenal (copyright), serta apa pun yang terbaca melibatkan anak di bawah umur. Mencoba ulang permintaan yang sama tidak akan membantu; ubah kata-kata prompt atau ganti gambarnya. Tingkat ketatnya berbeda antarmodel, jadi prompt yang sama bisa lolos di satu model dan ditolak di model lain.
Loop retry yang melakukan hal yang benar
Helper Python ini mencoba ulang apa yang layak dan berhenti pada apa yang tidak. Dua detail penting:
- Mengirim ulang submit setelah
503atau koneksi terputus memakai samaIdempotency-Keyyang sama, sehingga tidak akan pernah memulai job kedua yang berbayar. - Mencoba lagi setelah job gagal memakai kunci baru. Kunci yang sama hanya akan mengembalikan job yang gagal itu.
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"])Job contoh adalah klip Seedance 2.0 Fast 480p berdurasi 5 detik, yang berharga $0.25 jika berhasil dan gratis jika gagal. Batas max_cost_usd mencegah pengaturan yang salah menghabiskan biaya lebih dari perkiraan.
Menghindari error sejak awal
- Baca opsinya sebelum mengirim.
GET /v1/modelsdan halaman model mencantumkan ukuran, durasi, dan batas referensi setiap model. Nilai di luar daftar itu langsung ditolak dengan422 invalid_input. - Unggah file, jangan disematkan.
POST /v1/uploadsmenerima gambar hingga 30 MB, klip hingga 50 MB, dan suara hingga 15 MB, lalu mengembalikan tautan yang berlaku 14 hari, sehingga body permintaan tetap kecil. - Periksa saldo Anda lewat kode.
GET /v1/balancesebelum batch besar menghindarkan Anda dari rentetan error402. Paket kredit ada di halaman harga.
Untuk cara memangkas biaya job yang berhasil, lihat cara memangkas biaya API video AI. Referensi error lengkap ada di dokumentasi; dapatkan kunci API untuk mencobanya.
Pertanyaan yang sering diajukan
Apakah saya ditagih jika generasi video AI gagal?
Tidak. Harganya ditahan saat Anda mengirim dan dilepas kembali jika job gagal, apa pun penyebabnya.
Error mana yang perlu dicoba ulang?
Saat submit, coba ulang 429, 500 dan 503 setelah jeda Retry-After. Pada job yang gagal, coba ulang jika error.retryable bernilai true: model_busy, model_unavailable, timeout, dan all_routes_failed.
Apa arti content_policy?
Model menolak prompt atau media Anda, atau menahan hasil yang dibuatnya. Kolom reason menyebutkan aturan mana: sexual, minors, copyright, real_person, atau other. Ubah permintaannya, jangan dicoba ulang begitu saja.
Bagaimana mencoba ulang tanpa membayar dua kali?
Kirim header Idempotency-Key dan pakai kembali saat Anda mengirim ulang setelah timeout atau 503. Anda akan mendapat generasi yang sama, bukan generasi kedua.
Apa arti 422 invalid_input?
Model tidak menerima nilai yang Anda kirim, seperti durasi, ukuran, atau jumlah gambar referensi. Pesan error menyebutkan field-nya dan nilai yang diterima.
Bangun di atas API yang tidak pernah menagih kegagalan
Satu kunci API untuk semua model video dan gambar, dengan fallback otomatis antarrute. Kredit prabayar mulai $10, hanya ditagih untuk job yang berhasil.