Après avoir connecté Codex CLI à une API personnalisée, les erreurs se concentrent sur six niveaux : identifiants, chemin, modèle, limitation de débit, contexte et sandbox locale. Changer de modèle ou réinstaller l'outil dès qu'un message rouge apparaît transforme souvent un problème de dix minutes en une demi-journée. La méthode efficace consiste à figer les variables — même clé, même URL de base, même identifiant de modèle — et à ne modifier qu'un élément à la fois. Cet article décompose les erreurs par code de statut et indique l'emplacement des journaux, les commandes de diagnostic et un exemple de gestion d'erreur.
Remarque : OpenAI et Codex sont des marques d'OpenAI, Inc. Cet article est purement technique, sans affiliation ni coopération avec cette société. Configuration et libellés évoluent avec les versions ; la documentation de l'éditeur et la version courante font foi. Modèles et tarifs sont indiqués sur la page tarifs des modèles du site.
1. Lire le code de statut avant de toucher la configuration
| Symptôme | Signification courante | À vérifier en premier | Réessayer ? |
|---|---|---|---|
401 |
Clé absente, erronée ou invalide | Variable env_key, état de la clé, solde |
Non |
403 |
Clé sans permission ou bloquée par une politique | Permissions de modèle, état du compte, politique d'équipe | Non |
404 |
Chemin erroné ou interface inexistante | URL de base, prise en charge de /responses |
Non |
model not found |
Identifiant de modèle erroné ou non ouvert | Identifiant, permissions du compte | Non |
429 |
Débit, concurrence ou quota dépassés | Usage, clé partagée, réglages de tentative | Oui, après backoff |
400 context_length_exceeded |
Contexte au-delà de la limite du modèle | Volume d'entrée, sorties d'outils, compression | Oui, après modification |
| Échec sandbox ou approbation | Frontière de permission locale | Mode sandbox, répertoires inscriptibles, politique d'approbation | Oui, après ajustement |
| Délai d'attente ou flux interrompu | Proxy, TLS, inactivité, surcharge serveur | Chaîne réseau, paramètres de délai et de tentative | Selon le cas |
Ordre de diagnostic recommandé :
- Exécutez
codex doctordans le répertoire du projet : installation, configuration, authentification et environnement. - Dans la session,
/statusmontre modèle, politique d'approbation, répertoires inscriptibles et consommation de tokens. /debug-configaffiche les valeurs finalement effectives : confirmez que vous ne modifiez pas un fichier non chargé.- Validez l'URL de base, la clé et le modèle avec une requête minimale.
- Ajustez seulement ensuite le modèle, le contexte ou la politique de sandbox.
2. 401 et 403 : la clé n'atteint pas le processus
Le provider personnalisé de Codex désigne le nom de variable via env_key, par exemple :
[model_providers.zsqh]
name = "ZSQH AI Gateway"
base_url = "https://ai.zhongshangqihang.com/v1"
env_key = "ZSQH_API_KEY"
wire_api = "responses"
Une configuration correcte ne signifie pas que le processus lit la clé. Causes fréquentes : nom exporté dans le shell différent de env_key ; export dans un terminal A mais lancement dans un terminal B ; application lancée depuis l'interface graphique sans héritage des variables ; espaces, sauts de ligne ou guillemets autour de la clé ; clé appartenant à une autre plateforme ou un autre environnement ; clé supprimée, désactivée ou sans solde.
En environnement sans interface, CODEX_API_KEY peut transmettre la clé, mais ne conservez pas plusieurs sources simultanément : il devient impossible de savoir laquelle est réellement utilisée. Les 403 relèvent plutôt des permissions ou d'une politique : lisez le corps de réponse, puis la console de la passerelle, sans réessayer en boucle.
3. 404 et model not found : adresse, protocole et identifiant
Le provider personnalisé actuel n'accepte que wire_api = "responses" ; les requêtes visent /v1/responses. D'où plusieurs 404 fréquents :
base_urlomet/v1et la requête tombe sur une route web.base_urlcontient déjà/responseset le client l'ajoute une seconde fois, dupliquant le chemin.- La passerelle ne propose que
/v1/chat/completionset n'implémente pas le protocole Responses. - Le domaine est mal orthographié, ou l'adresse de la console est utilisée comme adresse API.
Renseignez base_url jusqu'à /v1, sans composer vous-même le chemin complet. Si le modèle n'existe pas, les passerelles renvoient 404 ou 400, souvent avec le champ model_not_found ; le corps de réponse fait foi. L'identifiant doit correspondre exactement à l'identifiant API de la page tarifs des modèles, casse, tirets et suffixe de version compris.
codex debug models exporte le catalogue local ou intégré, pas les modèles réellement ouverts par la passerelle. Vérifiez aussi que model_provider correspond au nom de [model_providers.xxx] ; en cas d'écart, Codex peut revenir au provider par défaut, donnant l'impression que « la configuration ne s'applique pas ».
4. 429 : réduire la concurrence avant de parler de tentatives
Un 429 signifie que la requête dépasse le débit, la concurrence ou le quota de tokens. Codex lit des fichiers et lance des commandes en continu, ce qui déclenche plus facilement la limite qu'un chat ordinaire. Scénarios courants : requêtes ou tokens par minute dépassés ; clé partagée par plusieurs personnes ; lecture massive de fichiers dans un grand dépôt ; tentatives sans backoff formant une tempête ; requêtes à contexte long saturant la concurrence.
La configuration du provider Codex contient request_max_retries (4 par défaut) et stream_max_retries (5 par défaut). Ils améliorent la stabilité, mais amplifient le volume en cas de 429 persistant ; baissez-les temporairement pendant le diagnostic.
Distinguez aussi limitation et impayé : si le corps d'erreur contient un champ du type insufficient_quota, réessayer ne sert à rien ; vérifiez le solde ou le quota dans la console. Pour une vraie limitation, lisez Retry-After ; sans cet en-tête, appliquez un backoff exponentiel avec gigue aléatoire. Des clés séparées par projet ou par personne facilitent le diagnostic.
5. Contexte dépassé : réduire l'entrée avant de changer de modèle
Le code d'erreur courant est context_length_exceeded, avec parfois « maximum context length ». La requête Codex ne contient pas seulement votre question : s'y ajoutent le prompt système, AGENTS.md, les fichiers lus, les sorties d'outils et l'historique. Sur une tâche longue, la sortie de chaque étape reste dans le contexte.
Ordre de traitement :
- Réduire le répertoire de travail pour que Codex ne lise que les modules concernés.
- Limiter les fichiers dans le prompt, éviter le scan du dépôt entier.
- Exclure les artefacts de build, dépendances, journaux et fichiers de clés.
- Utiliser
tool_output_token_limitpour limiter les tokens d'une sortie d'outil. - Ouvrir une nouvelle session et repartir d'un résumé court des conclusions.
- En dernier recours, passer à un modèle à contexte plus long.
model_context_window doit correspondre à la fenêtre réelle ; une valeur trop grande est quand même rejetée côté serveur. Un model_auto_compact_token_limit trop élevé peut heurter d'abord la limite dure. La fenêtre réelle fait foi selon la documentation de l'éditeur et la page de tarifs.
6. Échec sandbox et approbation : ce n'est pas une erreur API
Codex propose trois modes de sandbox : read-only, workspace-write et danger-full-access. read-only interdit les modifications ; workspace-write permet l'écriture dans les racines inscriptibles et peut activer le réseau ; danger-full-access supprime les frontières de fichiers et de réseau et ne convient qu'à un environnement contrôlé.
Les symptômes typiques sont Operation not permitted, Permission denied, ou une demande d'approbation en cours de commande. Vérifiez d'abord le mode et les répertoires affichés par /status, puis si le projet est hors de ces répertoires, si la commande exige le réseau et si un codex exec non interactif dispose d'une voie d'approbation.
Côté politique d'approbation, la version actuelle accepte on-request, never et granular. L'ancienne valeur approval_policy = "untrusted" n'est plus prise en charge et peut empêcher Codex de démarrer ; on-failure est également abandonnée. En CI, écrivez explicitement codex exec --sandbox workspace-write ; pour une tâche en lecture seule, --sandbox read-only --ask-for-approval never. N'utilisez pas danger-full-access par facilité.
7. Délais d'attente et flux interrompu : proxy, TLS et inactivité
Les requêtes en flux sont plus sensibles au réseau. Proxy d'entreprise, interception TLS, changement de VPN et sortie instable peuvent se traduire par « la requête part mais le premier token n'arrive pas », ou par une coupure en cours de flux.
stream_idle_timeout_ms vaut 300000 ms (cinq minutes) par défaut. Les modèles de raisonnement sont lents à produire le premier token ; une valeur trop basse les pénalise à tort. Si le proxy coupe une connexion inactive au bout de 60 secondes, augmenter le délai du client ne suffit pas : il faut aussi examiner la chaîne.
Pour une AC auto-signée ou une interception TLS, CODEX_CA_CERTIFICATE désigne un bundle PEM ; SSL_CERT_FILE n'est utilisé qu'à défaut. Ne désactivez pas la vérification des certificats. Après un délai dépassé, envoyez d'abord une requête minimale non streaming pour confirmer que l'API fonctionne, puis revenez à Codex.
8. Journaux et diagnostic : réunir les preuves avant de modifier
Le répertoire de journaux est contrôlé par log_dir, par défaut $CODEX_HOME/log. Le fichier texte codex-tui.log n'est généré que si log_dir est défini explicitement ; activez-le dans la configuration utilisateur pour le diagnostic.
Points d'entrée utiles :
codex doctor: rapport sur installation, configuration, authentification, environnement d'exécution et terminal./status: dans la session, modèle, politique d'approbation, répertoires inscriptibles et tokens./debug-config: source, priorité et valeur finale de la configuration.codex exec --json: flux d'événements JSON pour l'exécution non interactive.RUST_LOG: niveau de détail, par exemplecodex_core=debug,codex_tui=debug;codex execn'affiche par défaut que les erreurs.
Comparez la valeur finale de la configuration avec la requête réelle : URL de base, chemin /responses, nom du modèle, politique d'approbation. Beaucoup de « configurations sans effet » viennent d'un mauvais emplacement de fichier ou d'une variable non rechargée.
9. Un exemple réutilisable de gestion d'erreur
L'exemple ci-dessous s'adresse à votre propre script d'appel de la passerelle et ne remplace pas les tentatives intégrées à Codex CLI. Principe : ne pas réessayer les erreurs d'authentification et de chemin, réessayer avec backoff les limitations et les 5xx, modifier la requête pour les erreurs de contexte.
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
# Erreurs d'authentification, de permission, de chemin ou de modèle :
# corriger la configuration, ne pas réessayer
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("Contexte dépassé : réduire l'entrée ou ouvrir une nouvelle session")
raise RuntimeError(f"Format de requête incorrect : {resp.text[:300]}")
if resp.status_code in RETRYABLE:
if "insufficient_quota" in resp.text:
raise RuntimeError("Quota insuffisant : vérifier le solde, ne pas réessayer")
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("Nombre de tentatives épuisé")
Ce code ne traite pas le sandbox ni les approbations, qui relèvent de l'exécution locale. Séparer erreurs API et erreurs de permission locale accélère nettement le diagnostic.
Questions fréquentes
La clé fonctionne dans le test web, mais Codex renvoie 401 ?
Vérifiez le nom de variable lu par Codex et exportez-le dans le même shell que celui qui lance Codex. Les applications lancées depuis l'interface graphique ne voient souvent pas les variables récemment définies ; rouvrez l'application ou contrôlez l'authentification avec codex doctor.
Un 404 signifie-t-il forcément que le modèle a été retiré ?
Non. Codex utilise le protocole Responses : un chemin incorrect ou une passerelle sans point d'entrée /v1/responses renvoie aussi 404. Vérifiez d'abord que l'adresse s'arrête à /v1, puis l'identifiant du modèle.
Faut-il augmenter le nombre de tentatives en cas de 429 ?
Ce n'est pas conseillé. Un 429 persistant indique un dépassement : augmenter les tentatives ne fait qu'accroître le volume. Réduisez la concurrence, séparez les clés, lisez Retry-After et distinguez limitation et impayé.
Codex peut-il utiliser l'interface Chat Completions ?
Actuellement, seul wire_api = "responses" est accepté. Un point d'entrée uniquement Chat Completions nécessite une couche de conversion ou un autre client ; n'installez pas une ancienne version pour contourner le problème.
Peut-on désactiver le sandbox en cas d'erreur ?
Vous pouvez passer à workspace-write avec des répertoires inscriptibles, ou utiliser un mode plus permissif dans un environnement contrôlé, mais danger-full-access ne doit pas être la valeur par défaut. Consultez d'abord /status pour connaître les frontières.
Pour aller plus loin
Pour diagnostiquer Codex, l'ordre compte plus que l'astuce : lisez le code de statut et le corps de réponse, confirmez la configuration avec codex doctor et /debug-config, puis seulement modifiez le modèle ou le sandbox. Pour unifier clés, usage et point d'entrée modèle, vous pouvez créer un compte ZSQH AI Gateway ; le périmètre des modèles et des interfaces figure sur la page tarifs des modèles.
Lectures associées :
