APIConnectionError ou timeout na API da OpenAI: a falha é da sua rede, do SDK ou do serviço?

Ilustração de conexão falhando entre computador e servidor da OpenAI
Resposta rápida

APIConnectionError significa que a requisição não chegou ao servidor da OpenAI ou não conseguiu fechar uma conexão segura. APITimeoutError é um caso dessa família, e quando existe status HTTP (APIStatusError) o servidor chegou a responder. Para achar a origem, olhe o grupo APIs no status.openai.com, faça uma chamada mínima com curl medindo os tempos, repita fora da VPN ou do proxy e só depois mexa em timeout e max_retries no SDK

Fala aí, beleza? Seu código chamou a API da OpenAI pelo SDK de Python ou de Node e voltou um APIConnectionError, ou ficou pendurado até estourar o timeout 😛

A pergunta útil aqui é: em que ponto a requisição parou? O roteiro abaixo vai da sua rede local até o serviço da OpenAI, passando pelo SDK

O erro 429 fica de fora, porque ele tem artigo próprio. Se o erro aparece na interface do ChatGPT, no navegador, o caminho é outro, porque aí não tem SDK no meio

APIConnectionError, APITimeoutError e APIStatusError: qual a diferença no SDK da OpenAI

A diferença está em até onde a requisição chegou

No SDK Python, o README oficial descreve três situações:

  • APIConnectionError: a biblioteca não conseguiu chegar ao servidor, por exemplo por um problema de rede. A exceção original fica guardada em __cause__
  • APITimeoutError: é subclasse de APIConnectionError e vem com a mensagem Request timed out.
  • APIStatusError: a API respondeu com status que não é de sucesso (4xx ou 5xx). Ela traz status_code e response

O guia oficial de códigos de erro detalha o APIConnectionError: a requisição não chegou aos servidores da OpenAI ou não conseguiu estabelecer uma conexão segura

As causas listadas são rede, configuração de proxy, certificado SSL e regra de firewall

E em stream? Ao consumir um Stream ou AsyncStream, um timeout de leitura vira APITimeoutError e as outras falhas de requisição do HTTPX viram APIConnectionError

A recomendação do README é capturar as exceções do SDK, e não as do HTTPX

No Node, o README do openai-node diz que, quando a biblioteca não consegue se conectar ou recebe um status de erro, ela lança uma subclasse de APIError

No timeout, o erro é APIConnectionTimeoutError. O objeto traz err.request_id, err.status, err.name e err.headers

A leitura prática é simples:

  • Sem status HTTP: a falha está no caminho até o servidor (sua rede, proxy, firewall, certificado ou a própria conexão)
  • Com status HTTP: o servidor respondeu, então a conexão funcionou e a causa está no que ele devolveu

Timeout e retentativa padrão do SDK: o que acontece antes do erro aparecer

Antes de o erro chegar no seu código, o SDK já tentou de novo algumas vezes

Os dois SDKs oficiais, Python e Node, usam por padrão:

  • Timeout de 10 minutos
  • 2 novas tentativas automáticas, com backoff exponencial curto. Requisições que estouram o timeout também são repetidas duas vezes

São repetidos automaticamente os erros de conexão, 408 Request Timeout, 409 Conflict, 429 Rate Limit e status >=500

No Python tem um detalhe: o SDK só repete a requisição quando o corpo dela pode ser reenviado com segurança

O que isso muda no diagnóstico? Quando o APIConnectionError ou o timeout aparece no seu log, várias tentativas já falharam

Por isso o tempo total até o erro pode passar muito do timeout configurado. Não é o SDK "travado", é a soma das tentativas

Como descobrir se a falha é da sua rede, do SDK ou do serviço (passo a passo)

A ideia é eliminar uma camada por vez, da mais barata de checar para a mais trabalhosa

Você precisa de um terminal com curl e da chave exportada na variável OPENAI_API_KEY

  1. Olhe o status oficial, no grupo certo

Abra o status.openai.com. A página é pública, tem histórico de incidentes e separa os serviços em grupos: APIs, ChatGPT, Codex e FedRAMP

Pra quem chama a API pelo código, o que importa é o grupo APIs, que inclui componentes como Responses, Agents, Moderations, Realtime e Files

Erro comum deste passo: olhar o grupo ChatGPT e concluir que está tudo normal (ou que está tudo fora). ChatGPT e API aparecem separados. Se o seu problema for o agente de código, o raciocínio é parecido com o de quando o Codex trava ou não responde, só que olhando o grupo Codex

  1. Faça uma chamada mínima com curl, medindo os tempos

A referência oficial usa o endpoint de listar modelos como chamada mínima. Acrescente os limites de tempo e a medição:

curl https://api.openai.com/v1/models \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  --connect-timeout SEGUNDOS_CONEXAO \
  --max-time SEGUNDOS_TOTAL \
  -w '\n%{time_connect} %{time_starttransfer}\n'

Troque SEGUNDOS_CONEXAO e SEGUNDOS_TOTAL pelos limites que fazem sentido pra você. Segundo o manual do curl, --connect-timeout limita só a fase de conexão e --max-time limita a transferência inteira

No fim da saída aparecem dois números:

  • time_connect: tempo até a conexão TCP com o host (ou com o proxy)
  • time_starttransfer: tempo até chegar o primeiro byte da resposta

Como ler: se a conexão nem fecha e o --connect-timeout estoura, o problema está em chegar no servidor. Se conecta rápido mas o primeiro byte demora, a espera está depois da conexão

Erro comum deste passo: colar a chave literal no comando. Ela fica no histórico do shell e vaza fácil. Use sempre $OPENAI_API_KEY

  1. Repita a mesma chamada fora da VPN ou do proxy

Rode o mesmo comando ignorando o proxy pra esse host:

curl https://api.openai.com/v1/models \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  --noproxy api.openai.com \
  --connect-timeout SEGUNDOS_CONEXAO \
  --max-time SEGUNDOS_TOTAL \
  -w '\n%{time_connect} %{time_starttransfer}\n'

Ou desligue a VPN, ou rode de outra rede, ou de outra máquina

Se aqui funciona e no passo 2 não, a origem é local: proxy, firewall ou certificado. Bate com as causas que o guia oficial lista pro APIConnectionError

Erro comum deste passo: trocar duas coisas ao mesmo tempo (rede e máquina, por exemplo). Aí tu não sabe qual das duas resolveu

  1. Isole o SDK

Se o curl passa no MESMO ambiente onde o código roda e o SDK continua falhando, o problema está na configuração do cliente

Revise duas coisas:

  • Timeout curto demais pro tipo de chamada (ajuste na próxima seção)
  • Proxy no Node: o SDK usa o proxy configurado em fetchOptions. O exemplo oficial usa o ProxyAgent do undici:
const proxyAgent = new undici.ProxyAgent('http://localhost:8888');
const client = new OpenAI({ fetchOptions: { dispatcher: proxyAgent } });

O endereço http://localhost:8888 é o do exemplo do README: troque pelo proxy da sua rede

Erro comum deste passo: o curl usa o proxy do ambiente e o SDK não (ou o contrário), e aí um passa e o outro falha no mesmo computador

  1. Espere, tente de novo e acione o suporte se persistir

Para APITimeoutError, a orientação do guia oficial é tentar de novo depois de uma breve espera e procurar o suporte se o problema continuar

Chegue no suporte com os IDs da requisição em mãos (a seção de log mais abaixo mostra quais)

Como decidir com o resultado dos testes

Se o curl falha em todas as redes e o status mostra o grupo APIs normal, revise o que é comum a todos os testes: a chave, a máquina e o endpoint. Se continuar, siga o passo 5 e leve os IDs pro suporte

Se o curl falha só na sua rede, a origem é local: VPN, proxy, firewall ou certificado. Fale com quem administra essa rede

Se o curl passa e o SDK falha, o problema está no cliente: timeout, retentativa ou proxy configurado no código

E se o grupo APIs mostra incidente? Aí não adianta mexer no seu código, é acompanhar a página e tentar de novo depois 🙂

Como ajustar timeout e max_retries no Python e no Node

Sintoma: a chamada fica pendurada muuuito tempo antes de falhar, ou então falha cedo demais em tarefas longas

Causa: o padrão de 10 minutos com 2 novas tentativas não combina com o seu caso de uso

Solução no Python: dá pra configurar no cliente ou por requisição. O timeout aceita float em segundos

from openai import OpenAI

# no cliente inteiro
client = OpenAI(timeout=20.0)
client_sem_retry = OpenAI(max_retries=0)

# só em uma requisição
client.with_options(timeout=5.0)
client.with_options(max_retries=5)

Para tarefas longas, a documentação oficial dá este exemplo:

client = OpenAI(timeout=900.0)  # 15 minutos

Solução no Node: use as opções timeout e maxRetries, que também podem ir no cliente ou em cada requisição. Quando o tempo estoura, o erro é APIConnectionTimeoutError

E qual valor escolher? Pensa no tipo de chamada:

  • Chamada interativa (tem gente esperando a resposta na tela): timeout curto com retentativa, pra falhar rápido e tentar de novo
  • Job demorado (processamento em lote, tarefa longa): timeout longo, pra não matar uma requisição que só estava levando tempo

Erro comum: zerar os retries (max_retries=0) e depois achar que a API ficou instável. Sem retentativa, qualquer soluço de rede que o SDK absorveria vira erro no seu log

Como prevenir: defina o timeout por tipo de chamada com with_options (ou na requisição, no Node), em vez de mexer no valor global do cliente

O que registrar no log quando a API da OpenAI falha (sem expor a chave)

Sintoma: o erro acontece em produção e você não tem como provar pro suporte qual requisição falhou, nem quando

Causa: o log guarda só a mensagem da exceção

Solução: registre o que ajuda a localizar a requisição:

  • O tipo da exceção (APIConnectionError, APITimeoutError ou APIStatusError)
  • No Python, o __cause__, que mostra a falha original de rede
  • O status, quando existir
  • O request ID: _request_id na resposta de sucesso, exc.request_id ao capturar APIStatusError no Python, err.request_id no Node
  • Os cabeçalhos de depuração da resposta: x-request-id, openai-processing-ms e openai-version

A referência da API recomenda registrar os request IDs em produção pra agilizar o suporte

Um bloco de captura em Python que separa os três casos fica assim. Repara na ordem: APITimeoutError vem antes porque é subclasse de APIConnectionError

import logging
import openai
from openai import OpenAI

log = logging.getLogger("openai_calls")
client = OpenAI()

try:
    resposta = ...  # sua chamada à API aqui
except openai.APITimeoutError as e:
    log.error("timeout tipo=%s causa=%r", type(e).__name__, e.__cause__)
except openai.APIConnectionError as e:
    log.error("conexao tipo=%s causa=%r", type(e).__name__, e.__cause__)
except openai.APIStatusError as e:
    log.error("status=%s request_id=%s", e.status_code, e.request_id)

Isso é um exemplo didático: adapte o logger ao que você já usa

E quando não tem x-request-id? Em timeout ou falha de rede pode não existir resposta nenhuma, então não há ID da OpenAI pra guardar

Pra esse caso, mande o seu próprio identificador no cabeçalho de requisição X-Client-Request-Id e guarde esse valor no log. O suporte consegue conferir se a OpenAI recebeu a requisição. No curl fica assim:

curl https://api.openai.com/v1/models \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -H "X-Client-Request-Id: SEU_ID_UNICO"

Pra depurar no Python, ative o log do SDK com a variável de ambiente OPENAI_LOG=info. Os loggers do transporte HTTP são configurados à parte, pelo logging do próprio Python

Erro comum: logar os headers inteiros da requisição, incluindo o Authorization, que carrega a chave. Tome cuidado! Esse tipo de log costuma ir parar em ferramenta de observabilidade que meio mundo acessa

Como prevenir: filtre o Authorization antes de gravar e nunca salve o valor de OPENAI_API_KEY em log, nem em mensagem de erro

Vídeo complementar do canal

Bora conhecer outro lado da plataforma da OpenAI? O vídeo abaixo é sobre a Decisions API

Se o assunto te interessou, tem também o texto sobre o que é a Decisions API e o que dá pra automatizar com ela

Conteúdo complementar do Hora de Codar para conhecer o canal; não é uma demonstração específica desta notícia ou versão.

Próximo passo

Não espere o próximo incidente pra montar o kit

Deixe salvo no repositório um script com o curl do passo 2 (com --connect-timeout, --max-time e os tempos no -w) e uma variante com --noproxy

No código, deixe pronto o bloco de captura que separa APITimeoutError, APIConnectionError e APIStatusError, já gravando o request ID e mandando o X-Client-Request-Id

Assim, quando o erro voltar, tu roda o script, abre o grupo APIs no status e em poucos minutos sabe se o problema é seu, do SDK ou da OpenAI

Se quem reclamar for alguém usando o ChatGPT no navegador, o roteiro é outro, porque o problema não passa pelo SDK

Até o próximo post! =)

Perguntas frequentes

Receber APIConnectionError quer dizer que minha chave de API está errada?

Não necessariamente. Chave inválida costuma gerar uma resposta com status HTTP, que cai em APIStatusError, não em APIConnectionError, já que o APIConnectionError é exatamente a situação em que a requisição não chegou a ter resposta do servidor.


Quer aprender mais sobre inteligência artificial e programação na prática? Conheça o canal Hora de Codar no YouTube e acompanhe os próximos vídeos.

Escrito por | Matheus Battisti

Matheus Battisti
Fundador da Hora de Codar

Programador apaixonado pelo mundo das tecnologias, sempre buscando em aprender e se aprofundar em linguagens, frameworks e o que mais for necessário para executar um bom trabalho. Agora tem uma nova missão que é de passar seu conhecimento adiante para formar novos programadores e especializar mais os que já são.

Formações

Formação Vibe Coding

Formação Vibe Coding

Do Prompt ao Produto: Crie Software Real com IA

  • 474 aulas
  • 20 projetos
  • 39h 30min

Blog | Mais populares