ID ▾
Dapatkan Kunci API

Panduan Pemecahan Masalah Kode Error API Tanpa Sensor

Error bukan hal menakutkan; yang menakutkan adalah tidak tahu apakah harus mencoba ulang atau mengubah kode. Panduan ini mengurai setiap kode status: pemicu, diagnosis, dan perbaikan. Format error selalu JSON berisi objek error dengan code dan message, jadi langkah pertama selalu membaca body, bukan hanya kode status. Dilengkapi kode retry dengan backoff eksponensial, pembatasan laju klien, dan daftar periksa.

Diperbarui pada

Poin Penting

  • Hanya 429 dan 503 layak dicoba ulang secara otomatis; mencoba ulang kode status lain hanya akan membuang permintaan.
  • 402 no_credit berarti saldo habis atau uji coba berakhir; 403 content_blocked berarti konten diblokir. Keduanya bukan masalah jaringan.
  • Gunakan backoff eksponensial dengan jitter acak dan batas maksimum percobaan.
  • Setiap kunci dibatasi 300 permintaan per menit; tugas batch harus membatasi laju di sisi klien.

Format Error & Urutan Pembacaan

Semua respons gagal memiliki struktur yang sama:

{"error":{"code":"...","message":"..."}}

Urutan pembacaan tetap tiga langkah:

  1. Kode status HTTP menentukan kategori besar;
  2. error.code menentukan penyebab spesifik; gunakan ini untuk percabangan kode;
  3. error.message untuk manusia, catat di log, jangan gunakan untuk pencocokan string.

Pahami dulu batasnya: yang bisa diperbaiki dengan retry (429, 503, dan timeout jaringan) dan yang harus diubah (yang lain). Mengaburkan kedua kategori adalah akar penyebab insiden produksi, seperti melakukan retry terus-menerus pada 402 hingga menghasilkan puluhan permintaan tidak valid per detik.

Disarankan untuk mencatat empat bidang secara tetap di log: waktu, kode status, error.code, dan estimasi prompt_tokens permintaan ini. Saat terjadi masalah, Anda dapat langsung melihat apakah satu jenis error meningkat tiba-tiba atau kegagalan terjadi secara keseluruhan. Tambahkan aturan peringatan: beri notifikasi segera jika 402 muncul sekali karena berarti layanan tidak tersedia untuk pengguna; untuk 429, lihat proporsinya—kejadian sporadis tidak perlu ditangani, tetapi jika terus-menerus muncul berarti desain konkurensi bermasalah.

Tabel Cepat Kode Status

Kode Statuserror.codeArtiCoba Ulang?
400—Permintaan tidak valid, mis. prompt + max_tokens melebihi 100kTidak
401—Kunci tidak valid atau hilangTidak
402no_creditSaldo habis atau masa berlaku uji coba berakhirTidak
403content_blockedKonten diblokirTidak
404—Endpoint tidak ditemukanTidak
429—Memicu batas lajuYa, backoff
503upstream_busyLayanan sibuk sementaraYa, tunggu beberapa detik

Tanda “—” berarti tidak ada string code tetap yang perlu Anda tangani khusus; cukup gunakan percabangan berdasarkan kode status.

4xx: Perbaiki Permintaan, Jangan Coba Ulang

400 Permintaan tidak valid

  • Penyebab 1: Kesalahan format JSON, sering terjadi saat menulis string manual tanpa escape tanda kutip.
  • Penyebab 2: prompt + max_tokens melebihi 100,000. Percakapan panjang paling sering memicu ini.
  • Penyebab 3: Body permintaan melebihi 8 MB.
  • Perbaikan: serialisasi menggunakan pustaka JSON; estimasi token sebelum mengirim, potong riwayat atau kurangi max_tokens jika melebihi batas; lihatPanduan Praktis Konteks Panjang.

401 Masalah Kunci

  • Header hilang atau tidak ada awalan Bearer .
  • Kunci telah digenerate ulang; kunci lama langsung tidak valid, namun beberapa mesin masih menggunakan nilai lama.
  • Variabel lingkungan tidak diteruskan ke container atau tugas terjadwal.

402 no_credit

Saldo habis atau masa uji coba 7 hari telah berakhir. Kunjingi halaman akun untuk mengisi saldo prabayar agar layanan dapat dilanjutkan. Disarankan agar Anda memantau saldo layanan Anda sendiri agar tidak menunggu hingga pengguna melaporkan kesalahan.

403 content_blocked

Konten diblokir. Konten dewasa yang sah, fiksi, dan topik kontroversial tidak akan ditolak, namun konten seksual yang melibatkan anak di bawah umur akan selalu diblokir, termasuk dalam novel dan permainan peran. Jika Anda menerima 403, periksa apakah input atau riwayat percakapan mengandung konten tersebut; jangan hanya mengubah kata-kata dan mencoba lagi.

404 endpoint tidak ditemukan

Hanya ada dua endpoint: POST /v1/chat/completions dan GET /v1/models. Jika path tidak menyertakan /v1, memiliki slash berlebih, salah eja, atau Anda meminta endpoint embeddings atau gambar yang tidak didukung, Anda akan mendapatkan 404.

Ada satu jenis kesalahan 400 yang sering disalahpahami: token untuk percakapan panjang bertambah secara linear seiring jumlah putaran. Pengujian di siang hari mungkin berjalan lancar, tetapi setelah puluhan putaran, error 400 tiba-tiba muncul. Ini bukan karena ketidakstabilan API, melainkan karena jendela konteks telah penuh. Solusinya adalah membatasi riwayat percakapan; jika melebihi ambang batas, hapus putaran tertua atau kompres konten lama menjadi ringkasan. Jangan menunggu error muncul, perkirakan kapasitas sebelum mengirim permintaan.

Tips untuk men-debug 401: cetak empat karakter pertama dan terakhir dari kunci API ke dalam log, jangan cetak seluruhnya, lalu bandingkan dengan yang ditampilkan di halaman akun. Cara ini memastikan bahwa nilai yang dibaca oleh proses Anda adalah kunci yang Anda maksud, terutama dalam lingkungan container atau tugas terjadwal di mana variabel lingkungan mungkin hilang atau bernilai lama.

429 dan 503: Dua jenis yang perlu dicoba lagi

429 batas laju

Setiap kunci API dibatasi hingga 300 permintaan per menit. Tugas batch, beberapa instance yang berbagi satu kunci API, atau badai retry dapat memicu batas ini. Solusinya memiliki dua lapisan: klien membatasi laju terlebih dahulu (lihat kode di bawah), lalu lakukan retry dengan backoff untuk respons 429.

503 upstream_busy

Layanan sedang sibuk sementara. Coba lagi setelah beberapa detik. Jangan mengirim permintaan berturut-turut atau melakukan sepuluh kali percobaan dalam satu detik karena hal itu akan memperburuk situasi.

Timeout jaringan

Penghasilkan teks panjang membutuhkan waktu lebih lama, jadi jangan atur timeout terlalu pendek; gunakan 120 detik sebagai contoh. Perhatikan bahwa jika timeout terjadi, permintaan sebelumnya mungkin sudah dieksekusi di sisi server, sehingga panggilan ulang dapat menguras kuota secara berlebihan. Untuk permintaan generasi, batasi jumlah retry dan sebaiknya gunakan streaming untuk mengurangi waktu tunggu per sesi.

import os
import random
import time
import requests

URL = "https://api.wushenchaapi.com/v1/chat/completions"
HEADERS = {
    "Authorization": "Bearer " + os.environ["API_KEY"],
    "Content-Type": "application/json",
}
RETRYABLE = {429, 503}          # 只重试这两类
FATAL = {400, 401, 402, 403, 404}

class ApiError(Exception):
    def __init__(self, status, code, message):
        super().__init__(f"{status} {code}: {message}")
        self.status, self.code = status, code

def call(payload, max_retries=5, base=1.0, cap=30.0):
    for attempt in range(max_retries + 1):
        try:
            r = requests.post(URL, headers=HEADERS, json=payload, timeout=120)
        except (requests.ConnectionError, requests.Timeout):
            r = None                      # 网络层失败,按可重试处理
        if r is not None and r.ok:
            return r.json()
        if r is not None:
            try:
                err = r.json().get("error", {})
            except ValueError:
                err = {}
            if r.status_code in FATAL or r.status_code not in RETRYABLE:
                raise ApiError(r.status_code, err.get("code"), err.get("message"))
        if attempt == max_retries:
            raise ApiError(r.status_code if r is not None else 0, "retry_exhausted", "重试次数用尽")
        delay = min(cap, base * (2 ** attempt)) * random.uniform(0.5, 1.0)
        time.sleep(delay)

if __name__ == "__main__":
    out = call({"model": "uncensored", "max_tokens": 100,
                "messages": [{"role": "user", "content": "回复一个字:好"}]})
    print(out["choices"][0]["message"]["content"])

Poin penting: rumus backoff adalah min(cap, base × 2^n) × faktor acak. Jitter acak mencegah banyak klien melakukan retry secara bersamaan; status kode dalam kumpulan FATAL tidak dicoba lagi sama sekali.

Batasan laju klien dan permintaan diagnostik

Daripada menunggu 429 lalu melakukan backoff, lebih baik batasi laju terlebih dahulu. Alat kecil di bawah ini menjamin jumlah permintaan per menit tetap di bawah nilai yang ditetapkan dan aman untuk multithread:

import threading
import time

class RateGate:
    """简单的客户端限速:保证一分钟内请求数不超过 limit。"""
    def __init__(self, limit=240):          # 留出余量,低于 300/分钟
        self.limit, self.stamps, self.lock = limit, [], threading.Lock()

    def wait(self):
        while True:
            with self.lock:
                now = time.time()
                self.stamps = [t for t in self.stamps if now - t < 60]
                if len(self.stamps) < self.limit:
                    self.stamps.append(now)
                    return
                sleep_for = 60 - (now - self.stamps[0])
            time.sleep(max(sleep_for, 0.05))

Saat men-debug, cara paling bersih adalah memisahkan kode bisnis dan mengirim permintaan minimal menggunakan curl. Flag -i memungkinkan Anda melihat baris status dan header respons secara bersamaan:

curl -i https://api.wushenchaapi.com/v1/chat/completions \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model":"uncensored","max_tokens":20,"messages":[{"role":"user","content":"ping"}]}'

Jika curl berhasil tetapi kode bisnis gagal, masalahnya ada pada kode atau lingkungan Anda (proxy, variabel lingkungan, pengkodean). Jika curl juga gagal, periksa kunci API, saldo, dan jaringan.

Mengapa nilai batas laju ditetapkan 240 bukan 300: saat penyebaran multi-instances, setiap instance memiliki batas laju sendiri-sendiri, sehingga totalnya masih bisa melebihi batas keseluruhan; ditambah lagi, retry akan menduduki kuota. Menyisakan margin 20% adalah langkah yang lebih aman. Jika Anda memiliki beberapa instance, bagikan kuota setiap instance secara merata berdasarkan total, atau gunakan penghitung bersama untuk penjadwalan terpusat.

Daftar periksa troubleshooting

  1. Baca error.code di dalam body, jangan hanya melihat kode status.
  2. 401: Prefix kunci API, variabel lingkungan, apakah kunci telah dibuat ulang.
  3. 400: Apakah JSON valid, apakah jumlah token (prompt + max_tokens) melebihi 100,000, apakah body permintaan melebihi 8 MB.
  4. 402: Saldo dan masa berlaku uji coba.
  5. 403: Apakah input dan riwayat mengandung konten yang dilarang.
  6. 404: Apakah path adalah /v1/chat/completions atau /v1/models.
  7. 429: Apakah beberapa instance berbagi satu kunci API, apakah sudah diterapkan batasan laju di sisi klien.
  8. 503: Apakah sudah dilakukan retry dengan backoff, apakah intervalnya setidaknya beberapa detik.
  9. Timeout: Apakah timeout cukup lama, apakah Anda dapat beralih ke streaming.
  10. Jika semua di atas telah disingkirkan: gunakan curl untuk mereproduksi dengan permintaan minimal.

Jika baru saja melakukan integrasi, lihat terlebih dahuluTutorial Integrasi. Lebih banyak parameter terdapat didokumentasi.

Cara menggunakan daftar: saat terjadi masalah, singkirkan kemungkinan dari atas ke bawah secara berurutan, jangan melompat-lompat. Sebagian besar kesalahan "aneh" akhirnya bermuara pada empat poin pertama.

Tambahan pengalaman: tuliskan kembali kesimpulan troubleshooting ke dokumentasi tim. Pada kesalahan yang sama di masa depan, Anda dapat langsung mencocokkannya.

Pertanyaan Umum

Berapa lama harus menunggu sebelum mencoba lagi setelah menerima 503?

Beberapa detik sudah cukup. Disarankan untuk menunggu satu hingga dua detik pada percobaan pertama, kemudian tingkatkan secara eksponensial dan tambahkan jitter acak, serta tetapkan jumlah maksimum percobaan ulang.

Mengapa permintaan saya selalu menghasilkan 402?

Saldo habis atau masa berlaku uji coba 7 hari telah berakhir. Isi ulang saldo prabayar untuk melanjutkan; saldo tidak akan pernah kedaluwarsa.

Apakah 403 content_blocked dapat diatasi dengan mengubah prompt?

Jangan dicoba. Konten seksual yang melibatkan anak di bawah umur akan selalu diblokir dalam situasi apa pun, termasuk dalam novel dan roleplay. Konten dewasa normal tidak akan memicu error ini.

Apakah 429 dibatasi berdasarkan akun atau berdasarkan kunci API?

Batas laju diterapkan per kunci API, yaitu 300 permintaan per menit. Setiap akun hanya memiliki satu kunci API, jadi saat beberapa layanan berbagi kunci yang sama, mereka harus berbagi batas laju.

Isi formulir untuk mendapatkan kunci API

Buat akun, salin kunci API, dan ubah Base URL. Konfigurasinya sangat sederhana.