PT ▾
Obter chave de API

Códigos de erro e guia de solução de problemas da API sem censura

O erro não é o problema; o problema é não saber se deve tentar novamente ou modificar o código. Este guia analisa cada código de status: condição de gatilho, critério de decisão e correção. O corpo do erro é sempre JSON, com um objeto error contendo code e message, então o primeiro passo é ler o corpo, não apenas o código de status. Inclui código de tentativa com retrocesso exponencial, código de limite de requisições do cliente e uma lista de verificação.

Atualizado em

Pontos principais

  • Apenas 429 e 503 valem a tentativa automática; tentar novamente com outros códigos de status apenas desperdiça requisições.
  • 402 no_credit indica saldo esgotado ou teste expirado; 403 content_blocked indica conteúdo bloqueado. Nenhum é um problema de rede.
  • Tentativas devem usar backoff exponencial com jitter aleatório e um limite máximo de tentativas.
  • Cada chave permite 300 requisições por minuto. Tarefas em lote devem usar controle de taxa no cliente.

Formato do corpo de erro e ordem de leitura

Todas as respostas de falha têm a mesma estrutura:

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

A ordem de leitura é fixa em três etapas:

  1. Código de status HTTP, que define a categoria;
  2. error.code, que define a causa específica e deve ser usado para ramificação no código;
  3. error.message, para leitura humana e logs; não use para correspondência de strings.

Defina o limite: solucionáveis com tentativas (429, 503, timeout) e que exigem alteração (demais). Misturá-los causa falhas, como tentar novamente para 402.

Registre fixamente quatro campos nos logs: timestamp, código de status, error.code e a estimativa de prompt_tokens da requisição. Isso permite identificar rapidamente se um tipo de erro aumentou ou se as falhas são gerais. Configure um alerta: notifique imediatamente ao receber 402 (serviço indisponível); para 429, analise a proporção — esporádico é normal, contínuo indica problema de concorrência.

Consulta rápida de códigos de status

Código de statuserror.codeSignificadoTentar novamente?
400—Requisição inválida, como prompt + max_tokens ultrapassando 100kNão
401—Chave inválida ou ausenteNão
402no_creditSaldo esgotado ou crédito de teste expiradoNão
403content_blockedConteúdo bloqueadoNão
404—Endpoint não encontradoNão
429—Limite de requisições excedidoSim, com backoff
503upstream_busyServiço ocupado temporariamenteSim, após alguns segundos

O traço “—” na tabela indica que não há um código fixo específico para tratamento; use o código de status para ramificação.

4xx: corrija a requisição, não tente novamente

400 Requisição inválida

  • Causa 1: Erro de formatação JSON, comum quando strings são montadas manualmente sem escapar as aspas.
  • Causa 2: prompt + max_tokens excede 100.000. Diálogos longos são os mais propensos a isso.
  • Causa 3: Corpo da requisição excede 8 MB.
  • Correção: use uma biblioteca JSON para serialização; estime tokens antes de enviar e, se exceder, corte o histórico ou reduza max_tokens; veja Prática de contexto longo.

401 Problema com a chave

  • Header ausente ou falta o prefixo Bearer .
  • A chave foi regenerada, invalidando a antiga imediatamente, mas algum servidor ainda usa o valor antigo.
  • Variáveis de ambiente não foram passadas para o contêiner ou para tarefas agendadas.

402 sem_crédito

O saldo acabou ou o período de teste de 7 dias expirou. Vá para a página da conta para recarregar o crédito pré-pago e restaurar o acesso. Recomendamos que você monitore o saldo do seu serviço para não descobrir o problema apenas quando o usuário reportar um erro.

403 conteúdo_bloqueado

Conteúdo bloqueado. Conteúdo adulto legítimo, ficção e tópicos controversos não são rejeitados, mas conteúdo sexual envolvendo menores é sempre bloqueado, incluindo ficção e roleplay. Ao receber 403, verifique se há esse tipo de conteúdo no input ou no histórico; não adianta apenas reescrever e tentar novamente.

404 endpoint não encontrado

Existem apenas dois endpoints: POST /v1/chat/completions e GET /v1/models. Um caminho sem /v1, barra extra, erro de digitação ou o uso de endpoints não suportados como embeddings ou imagens resultarão em 404.

Outra classe de erros 400 fácil de mal interpretar: o número de tokens em conversas longas cresce linearmente com as rodadas. Tudo funciona bem durante os testes diurnos, mas após dezenas de rodadas, erros 400 começam a aparecer. Isso não é instabilidade da API, mas sim o limite da janela de contexto. A solução é limitar o histórico: descarte as rodadas mais antigas quando ultrapassar um limite ou resuma o conteúdo antigo. Não espere o erro para agir; estime o consumo antes de enviar a requisição.

Uma dica para investigar erros 401: imprima nos logs os quatro primeiros e os quatro últimos caracteres da chave, sem exibir o conteúdo completo, e compare com o que aparece na página da conta. Isso confirma se o processo está lendo a chave correta, especialmente em ambientes de contêiner ou tarefas agendadas, onde a ausência de variáveis de ambiente ou a leitura de valores antigos são causas comuns.

429 e 503: os dois casos para retry

429 limite de requisições

Limite de 300 requisições por minuto por chave. Tarefas em lote, múltiplas instâncias compartilhando uma única chave ou tempestades de retry podem acionar o limite. A correção tem duas camadas: limite de taxa no cliente (veja o código abaixo) e retry com backoff para 429.

503 upstream_busy

Serviço temporariamente ocupado. Aguarde alguns segundos e tente novamente. Não envie requisições em cascata imediatamente nem tente dez vezes em um segundo, pois isso piora a situação.

Tempo limite de rede

A geração de texto longo leva mais tempo; não defina o timeout muito baixo, use 120 segundos como exemplo. Ao fazer retry após timeout, lembre-se: a requisição anterior pode já ter sido executada no servidor, e chamadas duplicadas podem consumir saldo duas vezes. Para requisições de geração, reduza o número de retries e prefira streaming para encurtar o tempo de espera.

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"])

Resumo: a fórmula de backoff é min(cap, base × 2^n) × fator aleatório; o jitter aleatório evita que múltiplos clientes tentem retry simultaneamente. Os códigos de status na lista FATAL não devem ser retryados.

Limite de taxa no cliente e requisições de diagnóstico

Em vez de esperar o 429 para aplicar backoff, aplique limite de taxa antecipadamente. A ferramenta abaixo garante que o número de requisições por minuto fique abaixo do valor definido, sendo segura para múltiplas threads:

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))

Para diagnóstico, a abordagem mais limpa é isolar o código de negócio e enviar uma requisição mínima via curl. Use -i para ver simultaneamente a linha de status e os cabeçalhos de resposta:

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"}]}'

Se o curl funciona mas o código de negócio falha, o problema está no seu código ou ambiente (proxy, variáveis de ambiente, codificação). Se o curl também falha, verifique a chave, o saldo e a rede.

Por que o limite é 240 e não 300? Em implantações com múltiplas instâncias, cada instância aplica seu próprio limite, mas a soma pode exceder o total. Somado ao consumo extra de retries, é mais seguro deixar uma margem de 20%. Se você tem múltiplas instâncias, divida o limite total igualmente entre elas ou use um contador compartilhado para gerenciar o tráfego.

Lista de verificação de solução de problemas

  1. Leia o campo error.code no body, não confie apenas no código de status HTTP.
  2. 401: verifique o prefixo da chave, as variáveis de ambiente e se a chave foi regenerada.
  3. 400: verifique se o JSON é válido, se o prompt + max_tokens excede 100.000 tokens e se o corpo da requisição excede 8 MB.
  4. 402: verifique o saldo e a validade do período de teste.
  5. 403: verifique se há conteúdo proibido no input ou no histórico.
  6. 404: verifique se o caminho é /v1/chat/completions ou /v1/models.
  7. 429: verifique se múltiplas instâncias estão compartilhando uma única chave e se o limite de taxa no cliente está configurado.
  8. 503: verifique se o retry com backoff está implementado e se o intervalo é de pelo menos alguns segundos.
  9. Timeout: verifique se o timeout é suficiente e se é possível usar streaming.
  10. Se tudo mais falhar, reproduza o problema com uma requisição mínima via curl.

Se você acabou de começar, consulte primeiro o guia de integração. Mais parâmetros estão na documentação.

Como usar a lista: elimine itens de cima para baixo ao enfrentar problemas, não pule etapas. A maioria das falhas 'estranhas' acaba caindo nos quatro primeiros itens.

Dica adicional: registre as conclusões de cada solução de problemas na documentação da equipe. Na próxima vez que o mesmo erro ocorrer, você poderá identificar o problema imediatamente.

Perguntas frequentes

Quanto tempo esperar para tentar novamente ao receber 503?

Poucos segundos. Aguarde um a dois segundos na primeira tentativa, aumente exponencialmente depois, adicione jitter aleatório e defina um número máximo de tentativas.

Por que minhas requisições continuam retornando 402?

O saldo está esgotado ou o período de teste de 7 dias expirou. Recarregue o saldo pré-pago para retomar o uso; o saldo não expira.

O erro 403 content_blocked pode ser contornado reescrevendo o prompt?

Não tente. Conteúdo sexual envolvendo menores é sempre bloqueado, independentemente do contexto, incluindo ficção e roleplay. Conteúdo adulto legítimo não acionará esse erro.

O limite de 429 é por conta ou por chave?

O limite é de 300 requisições por minuto por chave. Como cada conta possui apenas uma chave, ao compartilhar entre múltiplos serviços, o limite de taxa deve ser compartilhado.

Basta preencher o formulário para obter a chave

Crie uma conta, copie a chave e altere o Base URL. A configuração é simples assim.