« Turn timed out after 600000ms » sur le fournisseur Codex de NanoClaw signifie que le WebSocket Responses de Codex a cessé d’envoyer des événements, et que la première erreur signalée par Codex n’arrive qu’après le déclenchement du minuteur de tour fixe de dix minutes de NanoClaw. Codex attend cinq minutes sur un flux inactif, réessaie silencieusement une première fois et ne signale que la deuxième tentative. Nous l’avons reproduit le 1er octobre 2026 avec Codex 0.138.0 — la version du rapport de bug — et 0.155.1, la version actuellement épinglée par NanoClaw, contre un endpoint local qui accepte la connexion puis reste silencieux.
C’est la reproduction derrière l’issue #3338 de NanoClaw, ouverte sans réponse d’un mainteneur lors de la vérification. Pour les choix de fournisseurs eux-mêmes, consultez Coût et fournisseurs de l’API NanoClaw ; si le bot reste silencieux sur Telegram pour d’autres raisons, consultez NanoClaw Telegram ne répond pas.
Ce que vous voyez
Un message envoyé au bot ne reçoit aucune réponse — aucune erreur ni réponse partielle — pendant dix minutes, puis une erreur apparaît. Les messages envoyés entre-temps semblent disparaître. Dans les journaux :
# Codex, inside the agent container (from the issue; our 0.155.1 run printed the same reason)
stream error: idle timeout waiting for websocket
stream disconnected - retrying sampling request (1/5 ...)
# NanoClaw, ten minutes after the message
Error: Turn timed out after 600000msCe que la reproduction a montré
| Secondes écoulées depuis le début du tour | Codex 0.138.0 | Codex 0.155.1 (version épinglée par NanoClaw) |
|---|---|---|
| ≈1–16 | Première requête envoyée via WebSocket ; aucune réponse | Une requête de préchauffage, fermée par Codex à 16 s ; la requête réelle suit |
| ≈300–316 | La première requête expire ; Codex renvoie la requête du tour — aucune notification | Délai d’inactivité ; tentative 1 journalisée — aucune notification |
| 600 | Le minuteur de NanoClaw termine le tour : « Turn timed out after 600000ms » | |
| ≈601–616 | Délai d’inactivité ; « retrying sampling request (1/5) » journalisé — toujours aucune notification (aucune du tout en 750 s) | Première error notification : « Reconnecting... 2/5 », « idle timeout waiting for websocket » — 15 secondes trop tard |
L’endpoint était un substitut qui acceptait le WebSocket sans rien envoyer ; le client était le véritable binaire app-server de Codex, piloté avec les mêmes appels que NanoClaw et évalué selon la propre règle de NanoClaw — toute notification d’erreur ou tout tour terminé y met fin ; sinon, le minuteur de dix minutes s’en charge.
Pourquoi la synchronisation est si mauvaise
- Codex attend 300 secondes le prochain événement sur un flux Responses avant de considérer le flux comme mort, puis réessaie jusqu’à cinq fois. Ce sont les valeurs par défaut du fournisseur OpenAI intégré dans les deux versions.
- Codex masque la première tentative WebSocket. Son code de nouvelle tentative le précise dans un commentaire — « In release builds, hide the first websocket retry notification to reduce noisy transient reconnect messages » — si bien qu’une interface ne reçoit rien avant la deuxième tentative, environ dix minutes plus tard.
- NanoClaw accorde exactement 600 000 ms à un tour Codex et y met fin sur toute notification d’erreur. Deux fenêtres d’inactivité plus le préchauffage de Codex dépassent cette durée ; avec les réglages par défaut, le minuteur l’emporte donc.
Les messages envoyés pendant le silence sont perdus
NanoClaw envoie un suivi qui arrive pendant un tour actif au turn/steer de Codex. Lors de l’exécution, Codex l’a accepté dans le tour bloqué sans rien envoyer de nouveau en amont ; après l’expiration, la reprise du fil affichait l’invite d’origine dans l’historique, mais pas le message de pilotage. C’est ce qui donne l’impression que le bot est complètement bloqué : tout ce que vous saisissez entre dans un tour qui ne se terminera jamais.
S’en sortir
Vérifié : après l’expiration, le message suivant reprend le même fil sur un nouvel app-server — ce que fait NanoClaw — et, lors de l’exécution, il s’est terminé en 0,16 seconde dès que l’endpoint a répondu. Il faut donc attendre l’expiration, puis renvoyer tout ce que vous avez saisi pendant le silence. Si le message suivant se bloque aussi, le problème vient toujours de la connexion en amont — vérifiez l’état d’OpenAI et, si le conteneur accède à OpenAI via un proxy, vérifiez si ce proxy transmet les mises à niveau WebSocket (la pull request #2672 décrit des proxys qui ne le font pas ; non testé ici).
Options qui raccourcissent l’attente, mesurées mais non livrées :
| Modification | Première erreur vue par NanoClaw | Conséquence |
|---|---|---|
| Codex via HTTP/SSE au lieu des WebSockets — PR #3851, ouverte, non fusionnée | 300 s : « Reconnecting... 1/5 » | La notification indique que Codex va réessayer, et il l’a fait, mais NanoClaw termine le tour à sa réception — un échec après cinq minutes au lieu de dix |
Codex stream_idle_timeout_ms = 60,000 sur les WebSockets | 136 s | NanoClaw écrit lui-même le fichier config.toml de Codex ; il s’agit donc d’une modification du code, pas d’un réglage que vous pouvez ajouter |
Les deux options terminent toujours le tour comme un échec. Ce que les mesures indiquent se situe du côté de NanoClaw — traiter une erreur qui réessaie comme une progression plutôt que comme une fin, ou mesurer le budget du tour depuis le dernier véritable événement — mais il s’agit d’une déduction issue de ces exécutions, pas d’un correctif confirmé par les mainteneurs.
Questions fréquentes
Pourquoi l’agent Codex de NanoClaw reste-t-il silencieux pendant dix minutes avant d’expirer ?
Parce que le premier signe de problème que Codex accepte de signaler arrive après que NanoClaw a déjà abandonné. Lorsque le WebSocket Responses cesse d’envoyer des événements, Codex attend l’expiration d’un délai d’inactivité de 300 secondes puis réessaie — et dans les versions de production, il masque délibérément la première nouvelle tentative WebSocket. La première notification d’erreur arrive après une deuxième fenêtre de 300 secondes, au-delà du minuteur fixe de tour de 600 000 ms de NanoClaw. Nous l’avons reproduit le 1er octobre 2026 : Codex 0.138.0 n’a envoyé aucune notification pendant 750 secondes, et 0.155.1 — la version actuellement épinglée par NanoClaw — a envoyé la première à 615,7 secondes ; la règle de NanoClaw a terminé le tour à 600.
Que deviennent les messages que j’envoie pendant que le bot est bloqué ?
Ils sont dirigés vers le tour bloqué et, lors de notre exécution, perdus. NanoClaw achemine tout suivi reçu pendant un tour actif vers turn/steer de Codex ; Codex l’a accepté dans le même tour bloqué, n’a rien renvoyé de nouveau en amont et, après l’expiration puis la reprise, le texte dirigé n’apparaissait pas dans l’historique du fil. Renvoyez tout ce que vous avez saisi pendant le silence une fois que le bot répond de nouveau.
Comment récupérer après l’expiration d’un tour Codex dans NanoClaw ?
Envoyez le message suivant. NanoClaw démarre un nouvel app-server et reprend le même fil ; lors de notre exécution, le tour repris s’est terminé en 0.16 seconde dès que l’endpoint a répondu, avec l’invite d’origine toujours présente dans l’historique. Si l’amont continue de bloquer, le nouveau tour se bloque de la même manière ; vérifiez donc d’abord l’état d’OpenAI ou votre chemin réseau — puis renvoyez les suivis qui ont été perdus.
Le passage de Codex à HTTP au lieu des WebSockets résout-il le problème ?
Il raccourcit le silence et n’est pas fusionné. La pull request #3851 (ouverte, par le rapporteur du problème) ajoute NANOCLAW_CODEX_TRANSPORT=http, qui achemine Codex via HTTP/SSE. Lors de notre exécution de cette configuration, la première notification d’erreur est arrivée à 300 secondes au lieu d’arriver après le minuteur — mais elle indiquait willRetry true alors que Codex renvoyait déjà la requête, et NanoClaw termine un tour à toute notification d’erreur ; le tour échouerait donc au bout de cinq minutes plutôt que de récupérer.
S’agit-il d’un délai d’expiration général de Codex ?
Non. Codex réessaie continuellement ; le silence de dix minutes vient de la façon dont le minuteur de tour de NanoClaw s’aligne sur la première nouvelle tentative masquée de Codex. En 0.155.1, l’app-server a signalé « Reconnecting... 2/5 » vers 616 secondes — un client avec un budget de tour plus long le verrait ; NanoClaw, jamais. Le fournisseur par défaut de NanoClaw est le Claude Agent SDK, qui n’intervient pas.
Reproduit le 1er octobre 2026 avec les binaires natifs codex app-server de npm (@openai/codex 0.138.0 et 0.155.1, darwin-arm64), pilotés via stdio avec les paramètres initialize, thread/start, turn/start et turn/steer de la branche providers de NanoClaw (commit 3959d1f055), contre un substitut Responses local via WebSocket et HTTP/SSE. Les valeurs par défaut de Codex et la première nouvelle tentative masquée proviennent de codex-rs aux tags rust-v0.138.0 et rust-v0.155.1. Non exécutés : l’orchestrateur et le conteneur de NanoClaw, OneCLI, Telegram ou le véritable endpoint d’OpenAI — le substitut reproduit un flux silencieux, pas la cause du silence du flux d’OpenAI. L’état de l’issue et de la pull request a été vérifié le même jour.