Después de conectar Codex CLI a una API personalizada, la mayoría de los errores se concentran en seis capas: credenciales, rutas, modelos, límites de peticiones, contexto y sandbox local. Reaccionar a un aviso en rojo cambiando de modelo o reinstalando la herramienta suele convertir un problema de diez minutos en medio día. Es más eficaz fijar las variables: la misma clave, Base URL e ID de modelo, y cambiar un solo elemento a la vez. Este artículo desglosa por código de estado e indica ubicación de registros, comandos de diagnóstico y ejemplos de manejo de errores.
Nota: OpenAI y Codex son marcas de OpenAI, Inc. Este artículo solo ofrece una explicación técnica y no tiene relación de afiliación ni de colaboración con dichas empresas. La configuración y los textos cambian según la versión; consulta la documentación oficial y la versión actual. Los modelos y precios figuran en la página de precios de modelos del sitio.
1. Mira primero el código de estado y luego toca la configuración
| Síntoma | Significado habitual | Qué revisar primero | ¿Reintentar? |
|---|---|---|---|
401 |
Clave ausente, incorrecta o inválida | Variable env_key, estado de la clave, saldo |
No |
403 |
La clave no tiene permiso o la política la bloquea | Permisos de modelo, estado de la cuenta, políticas del equipo | No |
404 |
Ruta incorrecta o interfaz inexistente | Base URL, compatibilidad con /responses |
No |
model not found |
ID de modelo incorrecto o no habilitado | Identificador del modelo, permisos de la cuenta | No |
429 |
Frecuencia, concurrencia o cuota excedida | Consumo, claves compartidas, ajustes de reintento | Sí, con retroceso |
400 context_length_exceeded |
El contexto supera el límite del modelo | Volumen de entrada, salida de herramientas, compresión | Sí, tras modificar la solicitud |
| Fallo de sandbox o aprobación | El límite de permisos local bloquea la operación | Modo de sandbox, directorios escribibles, política de aprobación | Sí, tras ajustar la política |
| Timeout o corte de streaming | Proxy, TLS, tiempo de inactividad, sobrecarga del servicio | Ruta de red, parámetros de timeout y reintento | Según el caso |
Se recomienda diagnosticar en este orden:
- Ejecuta
codex doctoren el directorio del proyecto para revisar instalación, configuración, autenticación y entorno de ejecución. - Dentro de la sesión, usa
/statuspara ver modelo, política de aprobación, directorios escribibles y consumo de tokens. - Usa
/debug-configpara ver los valores finales y confirmar que no estás editando un archivo que no se carga. - Valida Base URL, clave y modelo con una solicitud mínima.
- Solo después ajusta el modelo, el contexto o la política de sandbox.
2. 401 y 403: la clave no llega al proceso
El proveedor personalizado de Codex indica el nombre de la variable de entorno mediante env_key, por ejemplo:
[model_providers.zsqh]
name = "ZSQH AI Gateway"
base_url = "https://ai.zhongshangqihang.com/v1"
env_key = "ZSQH_API_KEY"
wire_api = "responses"
Tener la configuración correcta no garantiza que el proceso lea la clave. Causas habituales: el nombre exportado en la shell no coincide con env_key; se exportó en una terminal A pero se inició Codex en una terminal B; una aplicación lanzada desde la interfaz gráfica no heredó las variables; la clave tiene espacios, saltos de línea o comillas; la clave pertenece a otra plataforma u otro entorno; la clave fue eliminada, desactivada o no tiene saldo.
En entornos sin interfaz puedes pasar la clave con CODEX_API_KEY, pero no mantengas varias fuentes a la vez, porque será difícil saber cuál se usa al final. El 403 suele ser un problema de permisos o políticas: revisa primero el cuerpo de la respuesta y luego la consola del gateway; no reintentes en bucle.
3. 404 y model not found: dirección, protocolo e ID de modelo
El proveedor personalizado de Codex acepta actualmente solo wire_api = "responses", y las solicitudes van a /v1/responses. Esto genera varios 404 frecuentes:
base_urlomite/v1y la solicitud llega a una ruta web.base_urlya incluye/responsesy el cliente la añade otra vez, duplicando la ruta.- El gateway solo ofrece
/v1/chat/completionsy no implementa el protocolo Responses. - El dominio está mal escrito o se usó la dirección de la consola en lugar de la de la API.
Por lo general, base_url se escribe hasta /v1; no compongas tú la ruta completa de la interfaz. Cuando el modelo no existe, distintos gateways devuelven 404 o 400, y el campo de error suele ser model_not_found; decide según el cuerpo de la respuesta. El ID del modelo debe coincidir exactamente con el identificador de API de la página de precios de modelos, incluidas mayúsculas, guiones y sufijo de versión.
codex debug models exporta el catálogo local o integrado, no los modelos que el gateway ofrece realmente. Confirma también que model_provider coincide con el nombre de [model_providers.xxx]; si no coincide, Codex puede volver al proveedor predeterminado y parecer que «la configuración no surte efecto».
4. 429: primero baja la concurrencia, luego habla de reintentos
El 429 indica que la solicitud superó la tasa, la concurrencia o la cuota de tokens. Codex lee archivos y ejecuta comandos de forma continua, así que lo alcanza con más facilidad que un chat normal. Escenarios habituales: se excede el número de solicitudes o de tokens por minuto; varias personas comparten una clave; se leen muchos archivos seguidos en un repositorio grande; los reintentos no tienen retroceso y forman una tormenta; las solicitudes de contexto largo ocupan el espacio de concurrencia.
La configuración del proveedor de Codex incluye request_max_retries (4 por defecto) y stream_max_retries (5 por defecto). Mejoran la estabilidad, pero con un 429 persistente multiplican el volumen de solicitudes; durante el diagnóstico puedes bajarlos temporalmente.
También conviene distinguir entre limitación de tasa y falta de saldo: si el cuerpo del error contiene campos como insufficient_quota, reintentar no sirve de nada; revisa el saldo o la cuota en la consola. Para una limitación real, mira Retry-After; si no existe ese encabezado, aplica retroceso exponencial con jitter aleatorio. Separar claves por proyecto o por persona facilita localizar el origen mucho más que compartir una sola clave.
5. Contexto excedido: reduce primero la entrada, luego cambia de modelo
El código habitual de contexto excedido es context_length_exceeded, y el mensaje puede incluir «maximum context length». La solicitud de Codex no contiene solo tu pregunta: también incluye el prompt del sistema, AGENTS.md, los archivos leídos, la salida de herramientas y el historial. En tareas largas, la salida de cada paso anterior permanece en el contexto.
Orden recomendado de tratamiento:
- Reduce el directorio de trabajo y deja que Codex lea solo los módulos relevantes.
- Limita el alcance de archivos en el prompt y evita escanear todo el repositorio.
- Excluye artefactos de compilación, directorios de dependencias, registros y archivos de claves.
- Usa
tool_output_token_limitpara limitar los tokens de salida de cada herramienta. - Abre una sesión nueva y continúa con un resumen breve de las conclusiones ya obtenidas.
- Si de verdad es necesario, cambia a un modelo con más contexto.
model_context_window debe coincidir con la ventana real; si pones un número mayor, el servidor seguirá rechazando la solicitud. Si model_auto_compact_token_limit es demasiado alto, puede chocar antes con el límite duro. La ventana efectiva se rige por la documentación oficial y la página de precios.
6. Fallos de sandbox y aprobación: no son errores de API
Codex tiene tres modos de sandbox: read-only, workspace-write y danger-full-access. read-only no permite modificar archivos; workspace-write solo permite cambios dentro de los directorios escribibles y admite configurar acceso a la red; danger-full-access elimina los límites de archivos y red y solo es adecuado en entornos controlados.
Las manifestaciones típicas son Operation not permitted, Permission denied, o un comando que se detiene a mitad pidiendo aprobación. Revisa primero el modo y los directorios escribibles que muestra /status, y después confirma si el proyecto está fuera del directorio, si el comando necesita red y si el codex exec no interactivo tiene algún punto de aprobación.
En cuanto a la política de aprobación, la versión actual admite on-request, never y granular. El antiguo approval_policy = "untrusted" ya no es compatible y puede impedir que Codex arranque; on-failure también está obsoleto. En CI puedes indicar explícitamente codex exec --sandbox workspace-write; para tareas de solo lectura puedes usar --sandbox read-only --ask-for-approval never. No uses danger-full-access por comodidad.
7. Timeouts y cortes de streaming: proxy, TLS y tiempos de inactividad
Las solicitudes en streaming son más sensibles a la ruta de red. Un proxy corporativo, una inspección TLS, un cambio de VPN o una salida inestable pueden manifestarse como «la solicitud se envió pero el primer token no llega» o como un corte a mitad del flujo.
stream_idle_timeout_ms es 300000 milisegundos (cinco minutos) por defecto. Los modelos de razonamiento tardan más en el primer token, así que un valor demasiado bajo provoca falsos fallos; si el proxy corta las conexiones inactivas a los 60 segundos, aumentar el timeout del cliente no lo soluciona: hay que revisar también la ruta.
Para una CA autofirmada o inspección TLS puedes indicar un paquete PEM con CODEX_CA_CERTIFICATE; solo si no está definido se recurre a SSL_CERT_FILE. No desactives la validación de certificados de forma global. Tras un timeout, envía primero una solicitud mínima no streaming para confirmar que la API funciona y luego reproduce el problema en Codex.
8. Registros y diagnóstico: primero las pruebas, luego la configuración
El directorio de registros de Codex lo controla log_dir y por defecto es $CODEX_HOME/log. Solo cuando se define log_dir explícitamente se genera además el archivo de texto plano codex-tui.log; para diagnosticar, se recomienda activarlo en la configuración de usuario.
Entradas de diagnóstico habituales:
codex doctor: informe de instalación, configuración, autenticación, entorno de ejecución y estado de la terminal./status: dentro de la sesión, modelo, política de aprobación, directorios escribibles y consumo de tokens./debug-config: origen de la configuración, prioridad y valores finales.codex exec --json: salida de la ejecución no interactiva como flujo de eventos JSON.RUST_LOG: nivel de detalle de los registros, por ejemplocodex_core=debug,codex_tui=debug;codex execsolo muestra errores por defecto.
Durante el diagnóstico, contrasta los valores finales de configuración con la solicitud real: Base URL, ruta /responses, nombre del modelo y política de aprobación. Muchos casos de «la configuración no surte efecto» se deben a un archivo en la ubicación incorrecta o a variables de entorno que no se recargaron.
9. Un ejemplo reutilizable de manejo de errores
El siguiente ejemplo es para tus propios scripts que llaman al gateway; no sustituye los reintentos internos de Codex CLI. El principio es: no reintentar errores de autenticación ni de ruta, reintentar con retroceso las limitaciones y los 5xx, y modificar la solicitud ante errores de contexto.
import random
import time
import httpx
RETRYABLE = {429, 500, 502, 503, 504}
def call_gateway(payload: dict, key: str, url: str):
for attempt in range(4):
try:
resp = httpx.post(
url,
json=payload,
headers={"Authorization": f"Bearer {key}"},
timeout=httpx.Timeout(180.0, connect=10.0),
)
except httpx.TimeoutException:
if attempt == 3:
raise
time.sleep(min(30, 2 ** attempt) + random.random())
continue
# Errores de autenticación, permisos, ruta o modelo: corrige la configuración, no reintentes
if resp.status_code in (401, 403, 404):
raise RuntimeError(f"{resp.status_code}: {resp.text[:300]}")
if resp.status_code == 400:
body = resp.text.lower()
if "context" in body or "maximum context" in body:
raise RuntimeError("contexto excedido: reduce la entrada o abre una sesión nueva")
raise RuntimeError(f"formato de solicitud incorrecto: {resp.text[:300]}")
if resp.status_code in RETRYABLE:
if "insufficient_quota" in resp.text:
raise RuntimeError("cuota insuficiente: revisa el saldo, no reintentes")
retry_after = float(resp.headers.get("Retry-After", 2 ** attempt))
time.sleep(min(30, retry_after) + random.random())
continue
resp.raise_for_status()
return resp.json()
raise RuntimeError("se agotaron los reintentos")
Este código no gestiona sandbox ni aprobaciones, porque pertenecen a la capa de ejecución local. Separar los errores de API de los errores de permisos locales acelera mucho el diagnóstico.
Preguntas frecuentes
La clave funciona en la web, pero Codex devuelve 401. ¿Por qué?
Confirma el nombre de la variable de entorno que lee Codex y expórtala en la misma shell desde la que lo inicias. Las aplicaciones lanzadas desde la interfaz gráfica a menudo no leen variables recién definidas; reabre la aplicación o usa codex doctor para revisar la autenticación.
¿Un 404 significa siempre que el modelo se retiró?
No. Codex usa el protocolo Responses; una ruta incorrecta o un gateway sin endpoint /v1/responses también devuelven 404. Confirma primero que la dirección llega hasta /v1 y luego revisa el ID del modelo.
Para un 429, ¿conviene aumentar el número de reintentos?
No se recomienda. Un 429 persistente indica que ya se superó el límite y aumentar los reintentos solo incrementa el volumen. Baja la concurrencia, separa claves y revisa Retry-After para distinguir limitación de tasa de falta de saldo.
¿Codex puede usar la interfaz Chat Completions?
Actualmente solo acepta wire_api = "responses". Un endpoint que solo ofrece Chat Completions necesita una capa de conversión de protocolo o el cambio a otro cliente; no intentes evitarlo instalando una versión antigua.
¿Se puede desactivar directamente el error de sandbox?
Puedes pasar a workspace-write y configurar los directorios escribibles, o usar un modo de permisos más amplio en un entorno controlado, pero no se recomienda danger-full-access por defecto. Revisa primero los límites con /status.
Próximos pasos
En el diagnóstico de errores de Codex, el orden importa más que los trucos: mira primero el código de estado y el cuerpo de la respuesta, confirma después la configuración con codex doctor y /debug-config, y solo al final cambia el modelo o el sandbox. Si necesitas un punto de acceso unificado para claves, consumo y modelos, puedes registrarte en ZSQH AI Gateway; el alcance de modelos e interfaces figura en la página de precios de modelos.
Lecturas relacionadas:
