Error dan batas
Kode error GetVibe API: 401 (kunci), 402 (saldo), 403 (IP), 429 (batas laju). Cara menangani error dan mencoba ulang dengan exponential backoff.
Error yang dihasilkan GetVibe pada /v1/* memiliki envelope JSON dengan error.message, error.type dan error.code. Jangan mengandalkan teks pesan atau header layanan pihak ketiga sebagai kontrak.
Format error
{
"error": {
"message": "insufficient balance",
"type": "insufficient_quota",
"code": 402,
"request_id": "8d4b6b3a-..."
}
}Kode respons
| Parameter | Tipe | Deskripsi |
|---|---|---|
401 | authentication_error / 401 | Kunci tidak ada atau formatnya salah, atau kunci dinonaktifkan. Jangan mencoba lagi sampai kredensial diperbaiki. |
402 | insufficient_quota / 402 | Tidak ada saldo atau limit yang tersedia — menunggu tidak akan memperbaikinya. 402 tidak pernah menyertakan Retry-After dan tidak boleh dicoba lagi: isi ulang saldo, atau tunggu jendela langganan disetel ulang. |
403 | permission_error or policy type / 403 | IP, model atau kebijakan tidak mengizinkan permintaan. Jangan coba lagi tanpa mengubah permintaan atau pengaturannya. |
429 | rate_limit_exceeded, inflight_client_cap or rate_limit_error / 429 | Rate limit Anda, batas konkurensi Anda, reservasi saldo yang ditahan sebentar oleh permintaan konkuren Anda sendiri (penyebab reserved_in_flight), atau batas dari supplier. Coba lagi hanya setelah Retry-After; 429 tidak pernah berarti saldo Anda habis. |
410 | media_endpoint_retired / media_endpoint_retired | Hanya /v1/images/edits, /v1/video/generations, dan /v1/videos (sudah dihentikan). Jangan coba lagi; beralihlah ke /api/media/generate. /v1/images/generations tersedia. |
413 | invalid_request_error / 413 | Khusus Files API: file melebihi 50 MiB. Perkecil file, lalu buat permintaan baru. |
503 | overloaded / 503 | Edge global kelebihan beban. Coba lagi setelah Retry-After: 2. Error 503 lain mungkin tidak dapat dicoba ulang tanpa mengubah model atau permintaan. |
Error permintaan (400, 413, 422): kode dan perbaikan
Setiap error permintaan menyertakan error.code yang tetap dari tabel di bawah, error.param berisi kolom yang terkait (null jika model tidak menyebutkannya), dan tautan ke baris yang sesuai di akhir error.message — Codex dan CLI lainnya hanya menampilkan pesan, jadi tautan disertakan di sana.
| error.code | error.param | Yang harus dilakukan |
|---|---|---|
unsupported_parameter | nama kolom | Model atau kanal yang dipilih tidak menerima parameter ini. Hapus parameter tersebut dari permintaan (di Codex/IDE, dari konfigurasi) lalu coba lagi. |
invalid_parameter_value | nama kolom | Parameter disertakan, tetapi nilainya tidak diizinkan untuk model ini: misalnya temperature selain 1 saat penalaran aktif, max_tokens melebihi batas maksimum, atau effort "none" saat penalaran tidak dapat dinonaktifkan. Perbaiki nilainya sesuai petunjuk dalam pesan. |
missing_parameter | nama kolom | Kolom wajib tidak ada atau kosong. Tambahkan kolom tersebut. |
invalid_tool_schema | tools[].function.* | Definisi tool ditolak: nama hanya boleh menggunakan huruf Latin, angka, "_", dan "-"; parameter harus berupa JSON Schema dengan root type: "object". Atau pilih varian model lain. |
tool_choice_unsupported | tool_choice | Model tidak mendukung pemilihan tool secara paksa. Kirim tool_choice "auto" atau "none". |
invalid_tool_history | messages / input | Riwayat berisi pemanggilan tool tanpa hasil. Tambahkan hasil dengan id yang sama, atau hapus pemanggilan beserta hasilnya saat memangkas riwayat. |
invalid_image | — | Gambar tidak dapat dibaca. Kirim file PNG, JPEG, WebP, atau GIF yang lengkap (BMP, TIFF, AVIF, dan SVG tidak diterima). |
unsupported_input_modality | — | Model tidak menerima jenis lampiran ini (PDF, audio, video, gambar). Hapus lampiran tersebut atau pilih model yang mencantumkan jenis input tersebut dalam entri katalognya. |
conversation_state_unreadable | — | Penalaran dalam riwayat dibuat oleh kanal lain. Permintaan valid; coba lagi, dan jika error berulang, mulai percakapan baru. |
invalid_json | — | Isi permintaan bukan JSON atau diterima dalam keadaan terpotong. Untuk percakapan sangat panjang yang berisi gambar, mulai percakapan baru atau padatkan riwayat. |
request_too_large | — | Permintaan terlalu besar. Kurangi lampiran atau riwayat. |
request_rejected_by_channel | — | Kanal model menolak tanpa menyebutkan alasan; permintaannya sendiri kemungkinan besar valid. Coba lagi; jika penolakan berulang, pilih varian model lain (sufiks setelah titik dua) atau model tanpa sufiks. Jika itu tidak membantu, hubungi dukungan dengan menyertakan request_id. |
model_not_available_on_route | — | Rute belum disiapkan untuk model ini. Pilih model atau varian lain. |
context_length_exceeded | messages / input / prompt | Permintaan melebihi jendela konteks. Padatkan riwayat (di Codex: /compact) atau pilih model dengan jendela konteks yang lebih besar. |
content_moderation | — | Permintaan atau jawaban diblokir oleh filter konten penyedia. Ubah perumusannya atau pilih model lain. |
invalid_request | — | Penyebabnya tidak dikenali. Periksa permintaan berdasarkan referensi API; jika sudah benar, hubungi dukungan dengan menyertakan request_id dari respons. |
Header respons
| Parameter | Tipe | Deskripsi |
|---|---|---|
x-pv-cost-rub | string | Estimasi biaya rubel best-effort. Pada stream, x-pv-cost-rub tersedia saat estimasi input diketahui; pv_cost_rub pada event usage terakhir memerlukan x-pv-cost: 1. Riwayat penggunaan memuat jumlah debit yang sebenarnya. |
x-pv-generation-id | string | Id catatan riwayat penggunaan (GET /v1/generations/{id}). Dikembalikan hanya untuk permintaan chat/completions non-streaming. |
x-pv-dropped-params | string | Parameter permintaan yang dipisahkan koma yang tidak diterima oleh rute terpilih dan karena itu tidak dikirim ke model (misalnya temperature,top_p). Hanya ada bila memang ada yang ditahan, baik pada respons maupun pada galat. Kami tidak pernah membuang parameter secara diam-diam: tidak adanya header berarti semua yang Anda kirim sampai ke model tanpa perubahan. |
Retry-After | integer | Jumlah detik untuk menunggu. Edge menetapkannya pada 429 rate, 429 concurrency (5), 503 global overload (2) dan sebagian 402 sementara. Tidak diasumsikan untuk setiap 429/503. |
Error sebelum dan sesudah respons dimulai
Stream yang lambat (stream: true) menerima komentar 200 dan : pv-keepalive setelah 5 detik tanpa aktivitas agar koneksi tidak terlihat mati; permintaan non-stream yang panjang menerima 200 dan spasi setelah token pertamanya. Setelah itu status tidak dapat berubah dan error datang di body. Jika klien Anda beralih ke supplier lain saat terjadi error HTTP, kirim x-pv-honest-errors: 1 (atau minta dukungan mengaktifkannya untuk akun): dengan begitu tidak ada keepalive dan tidak ada 200 dini sebelum byte respons pertama, dan setiap kegagalan menjadi status HTTP biasa dengan body JSON. Konsekuensinya adalah socket yang senyap hingga token pertama; timeout header Anda harus mencakupnya.
Error setelah respons dimulai merupakan satu peristiwa terminal: untuk chat event: error dengan {"error":{message,type,code,status},"choices":[{"finish_reason":"error"}]} diikuti oleh data: [DONE]; untuk /v1/responses event: response.failed yang membawa error yang sama; untuk /v1/messages event: error milik Anthropic. code adalah penyebab mesin dan status adalah status HTTP yang seharusnya dimiliki error tersebut sebelum respons dimulai.
stream: true) x-pv-generation-id tidak dikembalikan karena penagihan selesai setelah streaming berakhir. Tinjau riwayat permintaan melalui GET /v1/generations.Batas rate dan konkurensi
Kedua batas bergantung pada saldo akun saat ini dan berlaku untuk semua API key akun tersebut secara bersamaan. Tier dihitung ulang secara otomatis: isi saldo dan batasnya naik; turun di bawah ambang batas dan tier akan turun. Tidak ada batas tokens-per-minute (TPM).
| Saldo dari | Permintaan per menit (RPM) | Permintaan bersamaan |
|---|---|---|
| 0 $ | 300 | 10 |
| 1 $ | 1 100 | 50 |
| 2 $ | 6 600 | 300 |
| 4 $ | 19 800 | 900 |
| 12 $ | 44 000 | 2 000 |
| Parameter | Tipe | Deskripsi |
|---|---|---|
429 rate_limit_exceeded | RPM | Akun mengirimkan jumlah permintaan dalam 60 detik terakhir (jendela bergulir) sebanyak yang diizinkan oleh tier-nya. Retry-After adalah jumlah detik hingga sebuah slot dalam jendela tersedia kembali (minimal 1); x-ratelimit-limit-requests adalah RPM Anda saat ini. Body: error.cause = key_rate_limited, error.details = { enforced_by: "getvibe", limit, unit: "requests_per_minute", retry_after_seconds }. |
429 inflight_client_cap | concurrency | Sebanyak mungkin permintaan sedang berjalan sesuai batas tier. Sebuah permintaan mempertahankan slotnya hingga selesai; sebuah stream mempertahankan slotnya hingga event terakhir. Retry-After: 5. Body: error.cause = account_concurrency_limited, error.details = { enforced_by: "getvibe", limit, unit: "parallel_requests", retry_after_seconds: 5 }. |
Personal limit | RPM | Jika akun memiliki batas permintaan pribadi, batas tersebut hanya dapat menurunkan RPM tier, tidak pernah menaikkannya. |
503 overloaded | service | Bukan batas Anda, melainkan perlindungan layanan: Retry-After: 2 adalah batas global untuk semua akun, sedangkan Retry-After: 1 berarti satu server sedang sibuk. Coba lagi setelah jeda tersebut. |
429 from a provider | upstream | error.cause = supplier_rate_limited berarti penyedia model membatasi permintaan dan batas Anda sendiri belum habis; channel_rate_limited adalah batas bersama dari channel penyedia (Retry-After: 10, tidak ada yang dikirim). |
Mencoba ulang permintaan
Untuk respons yang dapat dicoba ulang, pertama gunakan Retry-After jika ada. Tanpa header tersebut, jangan anggap 429 atau 503 apa pun otomatis dapat dicoba ulang: periksa status HTTP dan error.type publik, perbaiki penyebab yang tidak dapat dicoba ulang, dan gunakan backoff terbatas hanya untuk error sementara.
import time, requests
def call_with_retry(url, headers, payload, max_retries=5):
for attempt in range(max_retries):
r = requests.post(url, headers=headers, json=payload)
if r.status_code == 429:
# honor Retry-After, otherwise exponential backoff
wait = int(r.headers.get("Retry-After", 2 ** attempt))
time.sleep(wait)
continue
return r
return r