A API Qwen tem dois modos comuns de chamada: a interface nativa DashScope do Alibaba Cloud Bailian e a interface compatível com OpenAI. As estruturas de erro não são idênticas, mas a ordem de diagnóstico é a mesma: primeiro o status HTTP, depois o code e a message no corpo da resposta, em seguida o request_id, depois reproduza com uma requisição mínima e só então altere parâmetros ou troque de modelo.

Este artigo separa 401, 404, 429, 400, 5xx e timeout, com tabela de códigos, campos de log, código de retentativa e um checklist para antes de contatar o suporte. Modelos, cotas e cobrança seguem a documentação do fornecedor e a página de preços do site.

Nota: Qwen, Tongyi Qianwen, Alibaba Cloud, Bailian e DashScope são marcas do Alibaba Group e de seus titulares. Este artigo é apenas uma discussão técnica de diagnóstico e não implica vínculo de subordinação, representação ou parceria com essas empresas. Códigos de erro, critérios de limitação e comportamento da interface podem mudar entre versões; prevalecem a documentação do fornecedor e a resposta real.

1. Distinga primeiro o modo de interface e a estrutura de erro

A interface nativa DashScope normalmente retorna code, message e request_id no nível superior da resposta. A interface compatível com OpenAI segue o estilo OpenAI, com corpo de erro no formato {"error": {"message": "...", "type": "...", "code": "..."}}. No modo compatível, o request_id pode aparecer no cabeçalho ou no corpo; o nome do campo depende da resposta real.

Na engenharia, não analise apenas uma estrutura. Grave primeiro o corpo completo da resposta no log, sem alterações, e depois leia na ordem error.code e code de nível superior. Assim, ao trocar de modo de interface, o código de tratamento de erros não precisa ser reescrito.

2. 401: falha de autenticação, verifique primeiro a região

401 indica que a identidade não foi validada e normalmente não tem relação com capacidade do modelo ou saldo. No Bailian, as três falhas mais comuns são:

  • InvalidApiKey ou invalid_api_key: Key errada, cópia incompleta, ou Base URL incompatível com a região da Key.
  • invalid access token or token expired: token expirado, ou uso de endereço exclusivo de plano com uma Key comum.
  • NOT AUTHORIZED: WorkspaceId inválido, ou conta fora daquele workspace.

As Keys da Qwen são vinculadas à região. Keys de Pequim e de Singapura não podem ser misturadas. Este é o ponto mais fácil de esquecer: o código não muda, só a Base URL, e o 401 se repete de forma estável.

Diagnostique nesta ordem:

  1. Confirme se o cabeçalho é Authorization: Bearer <key>, com um espaço após os dois-pontos.
  2. Imprima o prefixo da variável de ambiente e confirme que não está vazia, desatualizada ou com quebra de linha.
  3. Verifique se Base URL e Key pertencem à mesma região.
  4. Confirme se o tipo de Key corresponde à interface: pagamento por uso, plano Coding e plano de tokens têm endereços diferentes.
  5. Troque por uma Key nova e faça uma requisição mínima para separar problema de Key de problema de proxy ou gateway.

3. 404 e 400: nome do modelo, ativação e contexto

404 na maioria das vezes não é falha do serviço, mas problema de nome ou disponibilidade do modelo. Em ModelNotFound ou model_not_found, verifique três coisas: se o nome está escrito corretamente, se o modelo foi ativado e se está disponível na região atual. model_not_supported indica que o modelo não suporta o modo compatível com OpenAI; é preciso trocar a interface ou o modelo.

As causas de 400 são mais variadas. InvalidParameter é parâmetro fora do intervalo, por exemplo temperature ou top_p fora da faixa. InvalidParameter.NotSupportEnableThinking indica que o modelo não suporta o parâmetro de modo de raciocínio. Contexto excedido geralmente retorna Range of input length should be [1, xxx], com código interno InternalError.Algo.InvalidParameter, ou então o comprimento total das mensagens ultrapassa o limite do modelo. A solução é cortar o histórico, resumir por blocos ou usar um modelo de contexto longo, não repetir a requisição.

4. 429: separe quatro tipos de limite e duas categorias de cota

429 é o erro mais sujeito a tratamento errado. No Bailian, o 429 inclui pelo menos as categorias abaixo; a tabela também lista erros de inadimplência e de serviço não ativado que costumam ser confundidos com limitação:

HTTP Código de erro Significado Indicado repetir
429 Throttling.RateQuota, LimitRequests Requisições por minuto (RPM) acima do limite Sim, com backoff
429 Throttling.AllocationQuota, insufficient_quota Tokens por minuto (TPM) acima do limite Sim, backoff e reduzir entrada
429 Throttling.BurstRate Proteção contra pico curto de tráfego Sim, suavizar o ritmo
429 Throttling.Concurrency Concorrência excessiva Sim, reduzir concorrência
429 AllocationQuota.FreeTierOnly Cota gratuita esgotada com modo "somente gratuito" ativo Não, recarregar ou desativar o modo
429 BudgetLimitExceeded Orçamento da conta esgotado Não, ajustar o orçamento
400 Arrearage Conta inadimplente ou em estado anormal Não, regularizar a conta
403 AccessDenied.Unpurchased Serviço não ativado Não, ativar primeiro

A limitação é contabilizada pela conta principal da Alibaba Cloud. Chamadas de subcontas RAM, workspaces e várias Keys são somadas. Portanto, "uma Key por serviço" não contorna a cota total; apenas evita disputa entre serviços. A limitação normalmente se recupera em nível de minuto; durante a espera, não repita em alta frequência.

5. Timeout e 5xx: localize em três segmentos

O timeout deve ser analisado em três partes: timeout de conexão geralmente é DNS, saída de rede ou proxy inacessível; primeiro token lento costuma ser fila no upstream ou entrada longa; timeout de leitura pode ser saída longa ou raciocínio demorado. O tratamento é diferente em cada caso; não basta aumentar o tempo limite.

No Bailian, RequestTimeOut indica requisição expirada, com limite documentado de 300 segundos; GatewayTimeout.InputDownload está relacionado ao download do arquivo de entrada. A interface compatível com OpenAI também pode retornar 503, indicando sobrecarga do motor. Quando um fluxo é interrompido, pode não haver código de erro: registre o conteúdo já recebido, o último trecho de dados e o motivo de encerramento, e só então determinar se foi oscilação de rede, corte do proxy ou timeout do upstream.

6. request_id e logs: a evidência do diagnóstico

A documentação informa que o request_id acompanha a resposta e pode estar no cabeçalho ou no corpo. Recomenda-se registro em duas vias: o cliente gera um trace_id que atravessa todas as retentativas e, ao mesmo tempo, guarda sem alterações o identificador do cabeçalho e o request_id do corpo. Se não houver registro, procure nos logs de monitoramento de modelos do console, desde que o log de inferência esteja ativado.

O log deve conter pelo menos: horário, trace_id, Base URL, região, nome do modelo, status HTTP, código de erro, mensagem, request_id, duração, número de tentativas e se é streaming. Registre apenas os primeiros caracteres da Key ou seu hash; não grave o texto do usuário nem a resposta completa em disco. Ao contatar o suporte, um registro com esses campos é muito mais útil do que "às vezes dá erro".

7. Retentativa e backoff: código de exemplo

O código abaixo desativa a retentativa automática do SDK, repete apenas 429 e 5xx recuperáveis e imprime status, código de erro e request_id juntos. Inadimplência, cota gratuita esgotada e orçamento excedido ficam fora do escopo de retentativa.

import os
import random
import time
import uuid

import httpx
from openai import OpenAI, APIConnectionError, APIStatusError, APITimeoutError

client = OpenAI(
    api_key=os.environ["DASHSCOPE_API_KEY"],
    base_url=os.environ.get(
        "DASHSCOPE_BASE_URL",
        "https://dashscope.aliyuncs.com/compatible-mode/v1",
    ),
    timeout=httpx.Timeout(connect=5.0, read=180.0, write=30.0, pool=10.0),
    max_retries=0,  # desativa a retentativa automática do SDK; a lógica abaixo controla tudo
)

RETRYABLE_429 = {
    "Throttling",
    "Throttling.RateQuota",
    "Throttling.AllocationQuota",
    "Throttling.BurstRate",
    "Throttling.Concurrency",
    "LimitRequests",
    "limit_requests",
    "ResourceExhausted",
}

def unpack_error(exc: APIStatusError):
    body = {}
    try:
        body = exc.response.json()
    except Exception:
        pass
    err = body.get("error", body) if isinstance(body, dict) else {}
    code = err.get("code") if isinstance(err, dict) else None
    request_id = None
    if isinstance(body, dict):
        request_id = body.get("request_id")
    request_id = (
        request_id
        or exc.response.headers.get("x-request-id")
        or exc.response.headers.get("x-dashscope-request-id")
    )
    return code, request_id, exc.response.text[:500]

def ask(prompt: str, model: str, max_attempts: int = 4) -> str:
    trace_id = uuid.uuid4().hex[:12]
    for attempt in range(1, max_attempts + 1):
        try:
            resp = client.chat.completions.create(
                model=model,
                messages=[{"role": "user", "content": prompt}],
            )
            return resp.choices[0].message.content
        except APIStatusError as exc:
            code, request_id, body = unpack_error(exc)
            print(
                f"trace={trace_id} attempt={attempt} "
                f"http={exc.status_code} code={code} "
                f"request_id={request_id} body={body}"
            )
            retryable = exc.status_code >= 500 or (
                exc.status_code == 429 and code in RETRYABLE_429
            )
            if not retryable or attempt == max_attempts:
                raise
        except (APITimeoutError, APIConnectionError) as exc:
            print(f"trace={trace_id} attempt={attempt} err={type(exc).__name__}")
            if attempt == max_attempts:
                raise
        wait = min(2 ** (attempt - 1), 30) + random.uniform(0, 1)
        time.sleep(wait)
    raise RuntimeError("tentativas esgotadas")

Três regras adicionais: se o servidor retornar Retry-After, respeite-o; controle o orçamento de retentativas globalmente para que vários serviços não amplifiquem o tráfego ao mesmo tempo; em requisições com efeitos colaterais, confirme primeiro se já foram executadas antes de reenviar.

8. Governança de concorrência: mais eficaz do que aumentar retentativas

Problemas de limite geralmente não se resolvem com retentativa, mas com governança na entrada:

  • Separe Keys por negócio e defina limites de concorrência distintos, para que uma tarefa em lote não derrube o serviço online.
  • Fragmente tarefas em lote e distribua horários, evitando picos no minuto cheio.
  • Use filas para suavizar picos; tarefas com falha vão para fila com atraso em vez de repetir sem controle.
  • Monitore a proporção de 429 e a latência p95; ao ver salto, reduza a concorrência primeiro.
  • Para tarefas offline, prefira a interface Batch e evite a limitação em tempo real.
  • Tenha um modelo ou entrada alternativa e confirme a compatibilidade de parâmetros antes da troca.

Os limites são configurados por modelo e conta; recarregar não eleva automaticamente RPM ou TPM. Se precisar de cota maior, faça solicitação comercial; não copie números de terceiros.

9. Checklist para antes de contatar o suporte

  1. Horário e fuso do incidente, e se foi contínuo ou esporádico.
  2. Base URL, região, caminho da interface, nome do modelo e método da requisição.
  3. Status HTTP, código de erro e mensagem completa.
  4. request_id; se não houver, informe o trace_id gerado por você.
  5. Uma requisição curl mínima reproduzível, com a Key mascarada.
  6. Se é streaming, contexto longo, ou se a configuração mudou recentemente.
  7. Escopo: uma Key, um workspace ou todo o serviço.

10. Perguntas frequentes (FAQ)

1. Todo 429 é limitação de taxa?

Não. O 429 também pode ser cota gratuita esgotada ou orçamento excedido; inadimplência pode retornar 400 Arrearage, e serviço não ativado pode retornar 403. Leia primeiro o código de erro e só então decida entre backoff, recarga ou ajuste de configuração.

2. O 401 continua mesmo com uma Key nova. O que fazer?

Verifique região e tipo de Key. As Keys da Qwen são vinculadas à região: uma Key de Pequim com endereço de Singapura retorna 401; endereço exclusivo de plano com Key comum também falha. Depois, confira cabeçalho, variáveis de ambiente e se o proxy reverso descarta a autenticação.

3. Como tratar contexto excedido?

Corte primeiro as mensagens antigas, remova anexos irrelevantes e parágrafos repetidos; depois resuma documentos longos em blocos ou use recuperação; se ainda não bastar, troque para um modelo de contexto longo. Não tente resolver entrada excessiva aumentando max_tokens.

4. Timeout deve ser repetido?

Faça retentativas limitadas apenas para falha de conexão e timeout de leitura, com backoff exponencial e teto. Em operações com efeitos colaterais, confirme antes se já foram executadas, para evitar pedido ou gravação duplicados.

5. Onde encontrar o request_id?

Primeiro no cabeçalho e no corpo da resposta; o nome do campo depende da interface. Se não houver registro, procure nos logs de monitoramento de modelos do console, com o log de inferência ativado. Ao contatar o suporte, envie também o trace_id e a requisição mínima de reprodução.

Próximos passos

Crie primeiro uma Key de teste no ZSQH AI Gateway, ensaie uma vez cada caso — 401, 404, 429, contexto excedido e timeout — e só então conecte o monitoramento de produção. Modelos disponíveis e formas de cobrança estão na página de preços.

Leitura relacionada