Saltar al contenido principal

Error de conexión de OpenAI API: corrige APIConnectionError probando la ruta

Ante APIConnectionError, conserva la causa original y comprueba la conexión desde el mismo proceso. Un fallo de DNS, de certificados o de proxy requiere una corrección distinta; después verifica la petición que fallaba.

LaoZhang AI TeamPublicadoActualizado 12 min de lectura
En esta página
Error de conexión de API: conservar la causa, distinguir transporte y HTTP, y confirmar la operación original

openai.APIConnectionError: Connection error. indica que el SDK no pudo completar la comunicación con el endpoint configurado. Empieza por capturar la causa original en el mismo proceso que falla, con un tiempo de espera explícito y sin reintentos automáticos durante esa comprobación. Después distingue un fallo de DNS, de TLS, del proxy o de lectura de la respuesta; cada uno exige una acción diferente.

Si ya tienes un código HTTP, lee esa respuesta antes de investigar la conexión. Un 401, un 429 y un 503 orientan hacia problemas distintos. Y si la respuesta se cortó después de enviar la petición —o después de recibir parte de un stream—, no puedes concluir que OpenAI no la procesó porque te falte el identificador. La referencia oficial de errores separa los problemas de conexión de los errores devueltos por la API.

Decisión rápida

Qué has recibidoPor dónde empezarAcción útil
APIConnectionError, sin estado HTTPCausa encadenada y configuración de red del procesoIdentifica DNS, certificado, conexión rechazada, proxy o desconexión antes de cambiar parámetros de la API
Excepción de timeoutFase que agotó el plazo y límites de la aplicaciónDistingue conexión, escritura y lectura; comprueba también el plazo del proxy o de la función
401Autenticación del servicio que respondióComprueba el host y la configuración de acceso; aumentar el timeout no corrige ese rechazo
429Cuerpo del error y cabecerasSigue la guía de causas del error 429 y reintentos; si indica insufficient_quota, revisa cuota y topes de gasto
500 o 503Servicio que emitió la respuesta y posible fallo temporalConserva estado, identificador y cabeceras útiles; consulta el estado de ese proveedor y aplica reintentos limitados cuando corresponda
Texto upstream connect error dentro de una respuesta HTTPProxy o pasarela que devuelve ese textoInvestiga su conexión con el siguiente servicio, sin atribuir automáticamente el fallo a OpenAI

Un 503 sigue siendo una respuesta HTTP, aunque describa que un intermediario no consiguió conectar con su destino. Tener cabeceras no demuestra que las haya generado OpenAI: una pasarela puede emitir su propio error.

Lee primero la evidencia de respuesta

Antes de modificar nada, anota el host de la URL base, el endpoint, la versión del SDK y el entorno donde falla: proceso local, contenedor, worker o función desplegada. Comprueba el valor que utiliza ese proceso, no solo el fichero de configuración que esperabas cargar. No copies claves ni URLs con credenciales a los registros.

En Python, APITimeoutError es una subclase de APIConnectionError; debes capturarla primero si necesitas distinguir ambas. APIStatusError expone status_code, response y request_id. Cuando falla el transporte, __cause__ ayuda a recuperar la excepción subyacente. La referencia actual del SDK de Python documenta estos campos y clases.

Este envoltorio se integra alrededor de la llamada existente, para conservar su cliente, endpoint, modelo y configuración. No crea otro cliente ni realiza una petición al importarlo:

python
import openai


def describir_causas(error):
    causas = []
    actual = error.__cause__
    while actual is not None and len(causas) < 6:
        causas.append(type(actual).__name__)
        actual = actual.__cause__
    return causas


def observar(llamada):
    try:
        resultado = llamada()
        print({
            "resultado": "respuesta recibida",
            "request_id": getattr(resultado, "_request_id", None),
        })
        return resultado
    except openai.APITimeoutError as error:
        print({"fallo": "timeout", "causas": describir_causas(error)})
        raise
    except openai.APIConnectionError as error:
        print({"fallo": "conexion", "causas": describir_causas(error)})
        raise
    except openai.APIStatusError as error:
        print({
            "fallo": "respuesta HTTP",
            "status": error.status_code,
            "request_id": error.request_id,
        })
        raise

Por ejemplo, sustituye el contorno de una llamada síncrona a client.responses.create(...) por observar(lambda: client.responses.create(...)), conservando sus argumentos. Es una integración ilustrativa: los puntos suspensivos representan tu operación existente. Para un cliente asíncrono, aplica el mismo orden de captura alrededor del await; no utilices este envoltorio síncrono.

Los nombres de las excepciones suelen bastar para empezar sin exponer datos. Si necesitas su mensaje completo, examínalo en un registro protegido y elimina credenciales, parámetros privados y contenido de clientes antes de compartirlo. No vuelques por defecto todas las cabeceras ni el cuerpo.

Controles SDK que conservan evidencia

Controles del SDK para distinguir timeout, conexión y respuesta HTTP sin ocultar la causa

Los SDK actuales de Python y JavaScript reintentan por defecto dos veces determinados fallos aptos para reintento. Durante una comprobación aislada, usa max_retries=0 en Python o maxRetries: 0 en JavaScript: así puedes relacionar el resultado con un único intento del SDK, siempre que tampoco reintente la cola o tu aplicación. Restaura después una política limitada acorde con el trabajo. Las referencias de Python y JavaScript describen estas opciones.

El timeout predeterminado documentado es de diez minutos. Python expresa el valor numérico en segundos; JavaScript, en milisegundos. Para una comprobación puedes aplicar client.with_options(max_retries=0, timeout=30.0) en Python o client.withOptions({ maxRetries: 0, timeout: 30_000 }) en JavaScript. Treinta segundos es un ejemplo para una operación pequeña, no una duración garantizada ni una recomendación para cualquier generación.

En Node.js, conserva también error.cause cuando exista. En el SDK actual, captura OpenAI.APIConnectionTimeoutError antes de OpenAI.APIConnectionError, y después OpenAI.APIError para leer status y requestID. Si la aplicación cancela con un AbortSignal, identifica esa cancelación y su plazo: aumentar el timeout del SDK no elimina un aborto que decide tu código. Consulta los errores y controles de tiempo del SDK de JavaScript.

Prueba la misma ruta sin confundir las comprobaciones

Las sondas de DNS, TLS y curl tienen un alcance distinto de la llamada instrumentada del proceso

Haz las pruebas desde el contenedor o la función que falla, con su DNS, certificados y salida de red. Que funcione tu portátil solo demuestra que tu portátil puede conectar. Incluso en la misma máquina, una terminal y un proceso pueden utilizar proxies o almacenes de certificados diferentes.

La comprobación más representativa es la llamada instrumentada anterior: mantiene el transporte del proceso. Para aislar una fase, añade una prueba más pequeña. Una prueba directa de TCP/TLS no atraviesa necesariamente el proxy del SDK, y curl tampoco reproduce automáticamente el transporte de Python o Node. Utiliza esas diferencias para comparar configuraciones, sin presentar una sonda independiente como prueba definitiva de la aplicación.

DNS, TCP y certificado desde Python

Esta función se ejecuta solo cuando la llamas. Úsala dentro del proceso afectado para probar una conexión HTTPS directa al host configurado. No lleva una clave API, no envía una petición de generación y mantiene la validación del certificado:

python
import socket
import ssl
from urllib.parse import urlsplit


def comprobar_conexion_directa(base_url, contexto_tls=None):
    destino = urlsplit(str(base_url))
    if destino.scheme != "https" or not destino.hostname:
        raise ValueError("Se necesita una URL HTTPS con host")
    host = destino.hostname
    puerto = destino.port or 443
    fase = "DNS"
    try:
        socket.getaddrinfo(host, puerto, type=socket.SOCK_STREAM)
        fase = "TCP"
        with socket.create_connection((host, puerto), timeout=5) as conexion:
            fase = "TLS"
            contexto = contexto_tls or ssl.create_default_context()
            with contexto.wrap_socket(conexion, server_hostname=host):
                print({"host": host, "resultado": "DNS, TCP y TLS correctos"})
    except (OSError, ssl.SSLError) as error:
        print({"host": host, "fase": fase, "causa": type(error).__name__})
        raise

Puedes pasar client.base_url de tu cliente existente. Si tu aplicación utiliza un contexto TLS corporativo autorizado, pasa ese mismo contexto; el contexto predeterminado puede usar otro conjunto de autoridades de confianza. El timeout de cinco segundos limita las operaciones de socket del ejemplo, pero no garantiza un plazo total de cinco segundos para la resolución DNS.

Si necesitas un proxy para salir, la imposibilidad de conectar directamente puede ser normal. En ese caso, comprueba el proxy mediante el transporte que utiliza la aplicación y sus registros autorizados. No cambies a una salida directa como supuesto arreglo.

Una sonda HTTP con curl

Para la API directa de OpenAI, esta comprobación sin autenticación prueba la ruta hacia /v1/models. No comprueba tu clave ni solicita inferencia:

bash
curl -q --connect-timeout 5 --max-time 15 \
  --output /dev/null \
  --write-out 'http=%{http_code} dns=%{time_namelookup} tcp=%{time_connect} tls=%{time_appconnect} total=%{time_total}\n' \
  https://api.openai.com/v1/models
resultado=$?
printf 'salida_curl=%s\n' "$resultado"

-q debe ser el primer argumento y evita cargar la configuración predeterminada de curl; no elimina las variables de proxy. Para Azure o una pasarela, utiliza una URL de comprobación documentada por ese proveedor y su configuración de red autorizada, sin enviar credenciales de OpenAI a un host distinto.

Interpreta por separado el estado HTTP y el código de salida. Un 401 con salida 0 significa que curl recibió una respuesta, no que la autenticación funcionó. Sin --fail, curl puede terminar con 0 aunque reciba un 429 o un 503. http=000 indica que la sonda no obtuvo un estado HTTP; no demuestra qué sucedió con otra petición de tu aplicación. Estas opciones y códigos aparecen en el manual de curl.

Salida de curlQué investigar
5 o 6Resolución DNS del proxy o del host, respectivamente
7Conexión TCP al destino o intermediario utilizado
28Fase que agotó el tiempo; consulta también los tiempos y el error
35, 60 o 77Negociación TLS, confianza del certificado o fichero de autoridades
52 o 56Respuesta vacía o fallo durante la recepción
97Negociación con el proxy

El código acota la investigación; no identifica por sí solo una causa única. Por ejemplo, un timeout puede producirse al conectar o al esperar una respuesta.

Ramas de ruta: corrige la causa que has encontrado

Resultado de la comprobaciónCorrección condicionadaCómo comprobarla
El host no se resuelve dentro del contenedorCorrige un host mal escrito o la configuración del resolvedor del despliegueVuelve a resolver el mismo host desde ese contenedor y repite la llamada instrumentada
DNS funciona, pero TCP es rechazado o agota el plazoRevisa la salida HTTPS autorizada, el firewall, NAT y la disponibilidad del proxy con el responsable de redConfirma conexión por la salida prevista; no basta con abrir un puerto en tu portátil
Falla la verificación del certificadoInstala o configura la cadena de confianza aprobada que necesita ese transporte, por ejemplo la CA corporativa de inspección TLSRepite TLS con el mismo contexto y nombre de host; la validación debe seguir activada
curl funciona, pero el SDK fallaCompara proxy, CA, URL base y transporte efectivo del SDKRepite desde el proceso con la configuración corregida, no solo desde la terminal
La respuesta empieza y luego se interrumpeRevisa el timeout de lectura y los plazos del proxy, balanceador o funciónConsume la respuesta completa con la operación original y registra dónde se corta
El error aparece solo al aumentar la concurrenciaComprueba espera por conexiones del pool y límites de la salida de redReduce la concurrencia de forma controlada y observa si desaparece la espera; después ajusta el recurso identificado

No desactives la verificación TLS para corregir un certificado ni fijes una IP para evitar el DNS. Ambas medidas cambian la prueba y pueden ocultar el problema que necesita reparar el despliegue.

Python: configura el cliente HTTP de tu versión

La referencia actual utiliza HTTPX2 y DefaultHttpx2Client; permite configurar proxy, transporte y un ssl.SSLContext con autoridades de confianza. Para separar fases, configura httpx2.Timeout con límites de conexión, lectura y escritura. Usa estas opciones únicamente si corresponden a la versión instalada de tu SDK. Algunas versiones anteriores utilizan HTTPX, httpx.Timeout y otro cliente predeterminado. No mezcles objetos de ambas bibliotecas ni copies nombres de la documentación actual sobre una instalación antigua. Consulta la sección de cliente HTTP personalizado en Python.

Reutiliza un cliente con una duración adecuada al proceso y ciérralo antes de terminar el bucle asíncrono. Si el fallo coincide con el cierre o la reutilización del cliente después de cerrarlo, corrige esa gestión antes de aumentar reintentos. Cambiar el código privado del SDK no es una configuración de transporte.

Node.js: el proxy debe corresponder al fetch utilizado

No presupongas que el fetch de tu entorno utiliza las variables de proxy de la terminal. En Node, el ejemplo actual del SDK combina el fetch de undici con su ProxyAgent y pasa el dispatcher mediante fetchOptions. Este fragmento requiere openai, undici y una URL de proxy autorizada en HTTPS_PROXY; muestra la construcción del cliente, sin efectuar ninguna llamada:

javascript
import OpenAI from "openai";
import { fetch as undiciFetch, ProxyAgent } from "undici";

const proxyUrl = process.env.HTTPS_PROXY;
if (!proxyUrl) throw new Error("Falta la URL del proxy autorizado");
const dispatcher = new ProxyAgent(proxyUrl);
const client = new OpenAI({
  fetch: undiciFetch,
  fetchOptions: { dispatcher },
  maxRetries: 0,
  timeout: 30_000,
});

El dispatcher no es una opción universal para cualquier implementación de fetch. En Bun y Deno, la configuración del proxy es distinta; sigue el apartado correspondiente de la referencia de JavaScript. Si tu entorno ya proporciona un transporte configurado, revisa ese transporte antes de sustituirlo.

Endpoint directo, Azure y pasarela

Para OpenAI directo, confirma que utilizas la URL base de OpenAI. En Azure, comprueba el endpoint del recurso y la configuración que requiere tu modalidad de acceso. En una pasarela compatible, verifica su URL base y sus reglas de salida: la compatibilidad del formato no convierte su red, certificados o errores en los de OpenAI.

Una ruta alternativa que funciona puede recuperar temporalmente una tarea autorizada, pero no prueba que la ruta original esté reparada. Conserva ambas observaciones y vuelve a probar el destino original después de corregirlo. Si la llamada sale del navegador, investiga también sus restricciones y evita exponer claves API; el diagnóstico del proceso de servidor es una comprobación diferente.

Comprueba la recuperación antes de reanudar el trabajo

Tras cambiar una sola causa identificada, envía una operación pequeña autorizada desde el mismo proceso, con la misma URL base, acceso, proyecto, endpoint y modelo que fallaban. Esta prueba de inferencia puede consumir saldo; una sonda sin autenticación no la sustituye.

La recuperación significa que esa operación termina correctamente, no solo que DNS responde o que recibes un 401. Conserva su identificador cuando esté disponible. Si el fallo original era un stream, consume el stream hasta el final: recibir el primer fragmento no verifica la lectura completa. Después aumenta el tráfico gradualmente para comprobar si reaparece un problema de conexiones o de plazos.

Un timeout no justifica repetir a ciegas. Puede haberse enviado el cuerpo y perdido la respuesta. Tampoco vuelvas a ejecutar automáticamente un stream que ya produjo contenido o una operación que dispara acciones posteriores. La referencia actual de Python indica que la lectura de streams puede generar errores y no se reproduce automáticamente al fallar. Decide cómo recuperar cada trabajo según su estado y su posibilidad de duplicación; un identificador de correlación no proporciona idempotencia.

Paquete de escalación

Si persiste, envía al equipo de red o al proveedor la hora con zona horaria, host y endpoint sin secretos, SDK y versión, entorno y región, excepción y causa subyacente, estado HTTP cuando exista y resultados de las comprobaciones. Añade qué cambió entre el fallo y el intento siguiente. Consulta OpenAI Status para la hora del incidente cuando el destino sea OpenAI; el estado general no descarta un fallo concreto de tu ruta.

Para solicitudes a endpoints de OpenAI que admiten esta cabecera, como Responses, Chat Completions y Embeddings, puedes añadir un X-Client-Request-Id único, explícito, ASCII y de hasta 512 caracteres. Si un timeout impide obtener x-request-id, ese identificador puede ayudar a soporte a buscar si recibió la petición. La referencia oficial de identificadores documenta su utilidad y alcance. No garantiza deduplicación, devolución del cargo ni compatibilidad con todas las pasarelas.

FAQ

¿APIConnectionError significa que OpenAI está caído?

No. También puede deberse al DNS, un certificado, un proxy o la salida de red de tu proceso. Identifica el destino y la causa encadenada, y consulta el estado del proveedor para la hora del fallo. Si ya recibiste un 503, conserva esa respuesta y averigua quién la emitió.

¿Por qué no hay request ID? ¿Se ha cobrado la petición?

La conexión puede haber fallado antes de llegar a la API, pero también puede haberse perdido la respuesta después del envío. La ausencia de identificador no prueba que la petición no se procesó ni que sea gratuita. Conserva el estado del trabajo y, para OpenAI, utiliza el identificador de cliente documentado al investigar nuevos intentos; soporte y los registros disponibles deberán aclarar lo sucedido.

¿Debo cambiar la API key?

Un error de conexión por sí solo no indica que la clave sea incorrecta. Si recibes un 401 del endpoint previsto, investiga la autenticación. Si falla DNS o TLS, cambiar la clave no corrige esa fase.

¿Aumentar el timeout soluciona Connection error?

Solo puede ayudar si el plazo es insuficiente para una operación que sigue progresando y el resto de la ruta permite esa duración. No corrige un certificado inválido, una conexión rechazada o un proxy mal configurado. Distingue además los plazos del SDK, de tu aplicación y de los intermediarios; el más corto puede cortar la respuesta.

Fuentes6

Páginas externas que cita esta guía, en el orden en que aparecen. Última actualización: 7 oct 2026.

  1. 1.referencia oficial de erroresdevelopers.openai.com/api/docs/guides/error-codes
  2. 2.referencia actual del SDK de Pythondevelopers.openai.com/api/reference/python
  3. 3.JavaScriptdevelopers.openai.com/api/reference/typescript
  4. 4.manual de curlcurl.se/docs/manpage.html
  5. 5.OpenAI Statusstatus.openai.com
  6. 6.referencia oficial de identificadoresdevelopers.openai.com/api/reference/overview