🧰 Codex/AI開発術 2026.07.26 更新

Codexのapply_patchが失敗する原因|差分不一致と文字コードを直す手順

Codexのapply_patchが失敗したとき、対象ファイルの読み直し、前後文脈の調整、改行・文字コードの確認、パッチ分割、適用後の検証までを順番に解説します。

Codexのapply_patchが失敗したときは、同じパッチを送り直す前に、パッチが想定した内容と現在のファイルが一致しているかを確認します。よくある原因は、対象行の変化、似た行の重複、パッチ形式の不備、改行や文字コードの違いです。

現行の公式実装では、対象行を見つけられないときに「Failed to find context」や「Failed to find expected lines」という表示が返ります。昔の版や一部の環境では「Invalid Context」という表現も見られますが、意味していることは同じで、「パッチが探している行が、いまのファイルに見つからない」という状態です。

復旧の基本は「現在状態を読む→失敗の種類を分ける→変更箇所を小さくする→適用後の差分を確かめる」です。依頼の整理にはCodexへの依頼テンプレートも使えます。

まず結論:同じパッチを再送する前に現在状態を読む

apply_patchのパッチは、待ち合わせのメモに似ています。「この目印の行を探して、そこを書き換える」という指示なので、目印の行が先に変わっていると、正しい場所にたどり着けません。だから失敗したら、まず対象ファイルを読み直します。

順番はこうです。

  1. 対象ファイルの、変更したい箇所とその前後を読み直す
  2. エラー表示から、失敗の種類を分ける(次の早見表)
  3. 現在の本文をもとに、小さいパッチへ作り直す
  4. 適用後に、差分・検索・テストで確かめる

失敗したときも読み直しが要るのには、実装上の理由があります。公式実装(apply-patch/src/lib.rs)には、途中で失敗しても、失敗する前に確実に反映できた変更を保持する仕組みがあります。つまり複数の変更を1つのパッチに入れていた場合、「一部だけ反映済み」の状態がありえます。ここで同じパッチをそのまま再送すると、反映済みの部分が二重適用になったり、別の不一致を起こしたりします。

症状別の切り分け早見表

症状・表示の例失敗している段階最初に確認するもの主な対処
「Failed to find context」「Failed to find expected lines」(旧版・環境では「Invalid Context」)対象行の照合(差分不一致)現在のファイル内容と直前の変更対象部分を読み直し、短い文脈で作り直す
「Invalid patch」「Invalid hunk」など、パッチを解析できない表示パッチ構文の解析開始・終了行、操作ヘッダー、各行の先頭記号公式形式に沿って囲みと記号を直す
ファイルがない、パスを開けないパス・入出力作業ディレクトリと対象パス実在する相対パスへ直す
sandbox、権限、承認に関する表示実行許可セッションの書き込み許可範囲許可範囲を確認し、必要なら承認手順を分ける
日本語や記号を含む箇所だけ一致しない文字表現文字コード、改行、不可視文字表示方法を変えて確認し、対象ファイルだけ直す

この4分類(差分不一致・構文・パス/権限・文字表現)は、公式実装の作りとも対応しています。パッチの囲みや行頭記号は解析段階(apply-patch/src/parser.rs)で検査され、対象行の照合はその後の段階で行われます。本文が合っていても囲みが欠けていれば解析で止まり、形式が正しくても対象行が無ければ照合で止まります。この2つを分けて調べると、直す場所を間違えません。

なお、エラーの表示名はCodexの版や実行環境で変わることがあります。特定の文字列だけを頼りにせず、最初に出たエラー表示の全体を読んでから分類してください。エラーだけで状態を判断しにくいときは、Codexが途中で止まる原因をログから切り分けるの手順で、実行した操作と最後の出力を分けて記録します。

差分不一致を直す:短い文脈で作り直し、小さく分ける

差分不一致(対象行が見つからない)と分かったら、対象ファイルを読み直します。別の変更が先に入った、整形ツールで空白が変わった、すでに修正済みだった、という可能性があるためです。

変更予定行だけでなく、その前後も含めて次を確認します。

  • 対象パスとファイル名が正しいか
  • 置き換えたい古い行が、いまも同じ順序で残っているか
  • インデント(字下げ)がスペースかタブか
  • 同じ文が複数ないか
  • 直前の編集で、変数名や関数名が変わっていないか

前後の文脈は「短く・現物から」

apply_patchは、変更しない周辺の行も目印として使います。公式の説明(prompt_with_apply_patch_instructions.md)では、変更箇所の前後にそれぞれ3行の文脈を置くのが基本例です。それでも場所が一意に決まらないときだけ、@@にクラス名や関数名を足して絞り込みます。

周辺コードを大量に貼ると、一致しなければならない条件まで増えて、かえって失敗しやすくなります。文脈は「現在のファイルからコピーした短い数行」にします。頭の中の記憶や、古いパッチからのコピーを使わないことが大切です。

*** Begin Patch
*** Update File: src/example.ts
@@
-const message = 'old';
+const message = 'new';
*** End Patch

形式の最小ルールはこうです。全体を*** Begin Patch*** End Patchで囲む。Add/Delete/Updateの操作ヘッダーを付ける。追加行は+、削除行は-、文脈行は半角スペースで始める。ファイル参照は相対パス(いまの作業フォルダから数えた道順)を基本にします。公式プロンプトは相対パスだけを使うよう指示しているため、迷ったら相対パスに揃えるのが安全です。

対象行がすでに'new'になっていたら、それは「修正済み」です。再適用せず、検証へ進みます。

1ファイル・1目的へ分割する

複数ファイルや複数関数を1回のパッチで変えると、1か所の不一致で全体が止まり、原因も見えにくくなります。目安は「1ファイル・1関数・1目的」です。

「関数名を変える」「呼び出し側を直す」「テストを更新する」を別のパッチに分け、各段階でファイルを読み直します。こうすると、先のパッチで文脈が変わっても追従でき、戻す範囲も小さくなります。ただし、途中状態でプログラムの構文が壊れるような分け方は避けます。広く点検したい場合は、AI生成コードの検品チェックリストが使えます。

文字コード・改行・不可視文字を切り分ける

見た目が同じでも、コンピュータの中での表現が違えば一致しないことがあります。候補は、改行コードのCRLFとLFの違い、UTF-8以外で保存された日本語ファイル、行末の空白、タブとスペース、全角に見える特殊な記号などです。

ただし、「空白や改行が違えば必ず失敗する」とは言えません。現行の照合処理(apply-patch/src/seek_sequence.rs)は、完全一致で見つからないときに、行末の空白を無視した照合、前後の空白を無視した照合、代表的なUnicodeのダッシュ・引用符・空白をASCII相当に読み替える照合まで、順に試します。つまり、ある程度の表記ゆれは実装側が吸収します。だからこそ、エラー文だけで「文字コードが原因」と断定せず、現在のファイルとエラーを観測してから特定します。

確認の手がかりは2つあります。

1つ目はGitの設定です。Gitのtext属性やeol属性は、行末をLFへ正規化したり、作業フォルダ側の行末をCRLFに指定したりできます。またworking-tree-encodingで作業ツリーの文字コードを指定でき、Shift-JISはUTF-8との往復変換に問題が知られていると公式文書(gitattributes)に書かれています。リポジトリにこれらの設定があると、「エディタで見た内容」と「保存された内容」がずれることがあります。

2つ目は、ファイルを書いた道具です。Windowsでは、Windows PowerShell 5.1はコマンドごとに既定の文字コードが一貫せず、PowerShell 6以降はテキスト出力がBOMなしUTF-8既定と、公式文書(about_Character_Encoding)で説明されています。「どの版の、どのコマンドで読み書きしたか」を確認すると、意図しない文字コード変更の出どころが分かります。

直すときの注意です。

  • 変換は、原因を確認した後の限定手段にする(最初の一手にしない)
  • 変換する前に、文字コードと改行を表示できるエディタで現状を確認する
  • 日本語がなどに化けているファイルは、元の文字コードが分かるまで上書きしない
  • 変換は対象ファイルだけに絞り、意味が変わっていないことを差分で確認する
  • 差分が全行に広がる場合は、機能修正と改行統一を別の変更に分ける

文字化けがすでに起きている場合は、先にUTF-8の文字化けを直す手順で、読み込み時の問題か書き込み時の問題かを切り分けます。

適用後と失敗後に差分・検索・テストで確かめる

成功表示が出ても、それだけでは修正完了とは限りません。逆に失敗表示でも、前半の変更だけ反映済みのことがあります(前述のとおり、失敗前に反映できた変更は保持されます)。成功でも失敗でも、次の順で確かめます。

  1. 変更した行と、その前後を読み直す
  2. 予定外のファイルや行が変わっていないか、差分を見る
  3. 置換前の文字列が、不要な場所に残っていないか検索する
  4. 対象に合う最小の構文検査やテストを実行する
  5. 実行できなかった検査と、その理由を記録する

テストがない場合は、ファイルの再読、検索、ビルドなど、観測できる証拠を組み合わせます。完了条件は「ツールが成功と表示した」ではなく、「狙った差分だけが入り、確認手段が通った」に置きます。

No such file or directory、sandbox、承認待ちなどの表示は、パッチ本文ではなく実行経路や権限の問題である可能性があります。パッチの文脈を何度も書き直す前に、作業ディレクトリ、対象パス、ログ、許可範囲を確認します。正確な表示名や挙動は環境差があるため、お使いの環境の公式案内で確認してください。権限に関する表示が出た場合は、Codexのsandbox・権限エラーを切り分けるも参照できます。

よくある質問

「Failed to find expected lines」と出たら最初に何をしますか?

対象ファイルを読み直します。エラーに出た置換前の行が、現在も同じ順序で存在するかを確認します。無ければ、現在の本文から短い文脈を取り直し、未反映の部分だけのパッチへ作り直します。

「Invalid patch」と差分不一致は同じエラーですか?

同じではありません。「Invalid patch」「Invalid hunk」は主に、囲みや行頭記号などパッチ構文の解析段階の失敗です。「Failed to find context」「Failed to find expected lines」は、解析が通った後の、対象行の照合段階の失敗です。前者はパッチの形式を、後者は現在のファイル内容を直します。

同じapply_patchをそのまま再実行してもよいですか?

先に対象ファイルを読み直してください。複数の変更を含むパッチでは、失敗前の変更が反映済みの可能性があります。反映済みの部分を除き、現在状態に対する未反映の差分だけへ作り直してから実行します。

CRLFとLFが違うだけで必ず失敗しますか?

必ずとは言えません。現行の照合処理は、行末や前後の空白を無視する段階も持つためです。改行、BOM、文字コード、不可視文字、そして対象行そのものの変化を、現物のファイルで切り分けてから原因を特定します。全ファイルの一括変換から入るのは避けます。

apply_patchのファイルパスは絶対パスでもよいですか?

公式プロンプトは相対パスだけを使うよう指示しています。作業ディレクトリを確認して、相対パスに揃えるのが基本です。一方で、現行の解析実装には絶対パスを受け入れるテストも含まれるため、「絶対パスは必ず構文エラーになる」とは断定できません。迷ったら互換性の高い相対パスを使ってください。

まとめ

apply_patchの失敗は、「読む→分ける→小さく直す→検証する」の順で片づきます。次の3つから始めてください。

  • エラーが出たら、同じパッチを再送する前に対象ファイルを読み直し、早見表で「差分不一致・構文・パス/権限・文字表現」の4種類に分ける
  • 現在の本文から短い前後文脈(基本は前後3行)を取り直し、「1ファイル・1関数・1目的」の小さいパッチへ作り直す。AIに直させる場合は、対象パス・現在の該当箇所・最初のエラー全文・期待する変更・実行した検査、の5点をそのまま渡す
  • 適用後は成功表示で終わらせず、差分の読み直し・置換前文字列の検索・最小のテストまたはビルドで、「狙った差分だけが入った」ことを確かめる

公式一次情報

確認日: 2026-07-26

続き(結論と実データ)はnoteに置いています

ここでは手順のところまで書きました。実際に出た数字、うまくいかなかった条件、そのまま使える設定ファイルは、 note の記事にまとめてあります。

noteで続きを読む Xをフォローする