Windows で Codex CLI が動かなくなった原因を切り分けて復旧した記録
Windows で Codex CLI が動かなくなった原因を切り分けて復旧した記録
Codexによるレビューの結果が、いつからか返ってこなくなっていた。exit codeは0のまま終わるので、出力を開くまで失敗に気づけない。8/12の日記レビューは、実際にそのまま素通りしていた。
結論
- PCにCodexが二つ入っていた。PATH上で呼ばれる方(mise経由、バージョン0.144.3)と、公式アプリが入れた方(バージョン0.147.0-alpha.6.6)
- あるバージョンから、Codexはファイルを読むたびにサンドボックス用の補助バイナリを起動する仕様に変わったらしい。mise側の配布物には、その補助バイナリが同梱されていなかった
- 公式アプリ版を優先して呼ぶランチャーに切り替え、動作を実測で確認した
- make-diaryのレビュー手順も直し、exit 0だけでは成功と判定しないようにした
静かな失敗に気づく
その朝の/make-diaryチェーンでは、Codexレビューの工程がすでに一度失敗していた。--sandbox read-onlyに変えても同じエラーで、ローカルファイルを一切読めない。「読み取り用の実行環境が一時的に起動できなかったため、対象を小分けにして再試行します」という応答が律儀に返ってきたが、小分けにしても結果は同じだった。helperバイナリがどのバージョンのCodexにも同梱されていないことをissueに記録し、その場は代役のレビューに切り替えて先へ進んだ。
チェーンが一通り終わったところで聞いてみた。「codexが動かない問題なんですけど、何が問題なんですか?」
二つのCodexと、消えたヘルパー
原因を確かめるところから始めた。まず、helperそのものが存在するかを探すと、公式アプリ版(0.147.0-alpha)の中に見つかった。そのディレクトリをPATHに足してmise版から呼ぶと、正しい答えが返ってきた。別の警告は残っていたが、「programが見つからない」というエラーは消えた。
続けて公式アプリの本体を直接呼んでみると、1,588ミリ秒でファイルを読み、正しい答えを返した。こちらは警告も出ない。
| 呼び出し方 | 実体 | バージョン | 状態 |
|---|---|---|---|
codex(PATH上、mise版) | mise/installs/codex/0.144.3 | 0.144.3 | サンドボックスhelperが同梱されず失敗 |
| 公式アプリ版 | OpenAI/Codex/bin/(ハッシュ付き) | 0.147.0-alpha.6.6 | helper同梱、正常動作 |
インストール時刻とエラーの初出時刻を突き合わせてみた。
| 日時 | 出来事 |
|---|---|
| 08-11 11:48 | 公式アプリ版0.147.0-alpha.6.6が入る |
| 08-12 07:06 | 翌朝のレビューからhelper起動失敗が始まる |
| 08-12 07:57 | 計画書レビューも同じエラーで失敗 |
| 08-13 07:09〜07:14 | この日もレビューが失敗し続ける |
| 08-13 07:39 | この1回だけ成功。公式アプリ版のhelperがフルパスで起動していた |
公式アプリ版が入った翌朝から、mise版の失敗が始まっていた。アップデートのどこかで壊れたのではないか、という程度の勘があったが、その勘は当たっていた。壊れていたのは「Codex本体」ではなく、「PCに二つ入っているCodexのうち、PATH上の方だけが更新に取り残されていた」という形だった。
helperのディレクトリをPATHに足すだけの応急処置でも、エラー自体は消える。ただしCreateProcessWithLogonW failed: 2という別の警告が残ったままで、サンドボックス本来の経路を通らずに答えを返している形だった。
原因を確定させた直後、セッションの接続が切れた。
「うん、ありがとう。じゃあ、引き継ぎドキュメント作ってください。」
memo/2026-08-13/handoff-codex-and-make-diary.mdに、確認済みの事実と選択肢を残した。選択肢は3つ。公式アプリ版をデフォルトにする案、mise側を最新版に上げる案、helperのディレクトリだけPATHに足す応急処置の案だった。mise側を上げる案は、helperが同梱されているかを確認しないうちは賭けになる。応急処置は警告が残ったままだ。承認して、公式アプリ版を優先するA案を採った。
ランチャースクリプトを作らせ、codex.exe、codex-windows-sandbox-setup.exe、codex-command-runner.exeの3点が揃った最新ディレクトリだけを選ぶようにした。3点が揃わなければmise版へ黙って戻さず、失敗させる。PATHではランチャーをmiseのshimより手前に置き直し、mise側の設定からはCodexのエントリを外した。
where.exe codexの先頭がランチャーに変わり、codex --versionはcodex-cli 0.147.0-alpha.6.6を返した。issueファイル自身をレビューにかけると、対象を実読し、成功のログと最終判定まで含む68,356バイトの出力が返ってきた。
積み残しを棚卸しする
引き継ぎドキュメントを作ったあと、「魅力事項をリスト化してください」と頼んだ。聞き間違いだったが、「未了事項」と読み替えて棚卸しにかけると、memoの計画書212本のうち動いているのが34本、状態不明が130本、Googleタスクの期限超過が4件、未解決issueが21件あった。
直近で手が付いていたものから順に並べてもらい、そこから図解カタログまわりの計画書2本を実物と突き合わせる作業に入った。
復旧を実戦で確かめる
別の調査(図解カタログの作業がmasterと別worktreeで食い違っていないかを確かめる件)が一段落したところで頼んだ。「一応念のためにcodexにも同じようなリクエストを投げて、あなたの回答と同じになっているかを確認してください。」
照合したかったのは Claude Code が出した結論のほうだ。その結論は伏せたまま、Codex には独立に調べさせた。誘導を避けるためである。返ってきた答えは Claude Code の結論と一致していたが、そのぶん説明の側の誤りが1つ浮かんだ。調査を始めた時点のmasterのハッシュが、並行して動いていた別セッションの分だけ先に進んでいたことに気づいていなかった。実測して確かめると、Codexの指摘どおりだった。
その後の計画書レビューでも、Codexにかけると致命的な指摘が3件出てきた。3件とも自分の側の見落としで、実測で裏を取ってすべて反映してからプッシュした(a321b064..faab3e3c)。
静かな失敗を見逃さない仕組みに変える
exit 0を返していても、中身が空なら失敗と同じだ。make-diaryのレビュー手順を直し、結果ファイルが空でないこと、ファイル読み取りの成功ログ(succeeded in)が出ていること、最後に判定の一行があることの3つを機械的に確認するようにした。3つのうち1つでも欠ければ、「レビュー結果0件」ではなく「レビュー失敗」と報告する形に変えた。
同じコミットで、手順書と.gitignoreが食い違っていた点も一緒に直した。position-newsの非公開記事はコミット対象から外し、実行状態のファイルだけをコミットする運用に揃えた。この修正は一度ブランチへ切り出し、プルリクエストにしてからmasterへ取り込んだ。
学んだこと
- exit 0だけでは成功と判定できない。空振りかどうかは中身を開くまで分からない
- 同じCLIが2つ入っていると、更新のたびにどちらが最新かがずれる。今回はPATH上で呼ばれる方だけが取り残されていた
- ハッシュ付きのインストール先パスは更新のたびに変わる。固定パスで呼ぶのではなく、必要なファイルが揃った最新ディレクトリを選ぶ形にした
- 応急処置でエラーが消えても、警告が残っているなら本来の経路を通っていないことがある。エラーの消失と復旧は同じではない
同じ日の別のコミットでは、学習ゲートの小テストで1問だけ間違えた。選んだ答えは「マス分割でpremature-wrap警告が出るため」だったが、lintは図形の分け方までは見ていない。解説を受けてから解き直し、5問中5問で合格して受領証を受け取った。確認を怠らないという点は、Codexの一件だけでなく、その日の別の場面にも表れていた。
結果が返ってきたかどうかは、exit codeだけでは分からない。中身を開いて確かめるところまでが、レビューという工程なのだと思い知らされた1日だった。