故障处理

Codex apply_patch 失败?从上下文不匹配到写入结果逐步排查

Codex 修改文件时反复出现 apply_patch verification failed、Failed to find expected lines?先区分补丁上下文、路径与工具执行问题,再按当前文件做最小修改,用 diff 和实际内容确认结果。

Codex 已经读过文件,也说清了修改方案,但一到写入就出现 apply_patch 失败。先保留工具名、完整错误和目标文件路径,暂停对同一个补丁的连续重试:问题可能出在补丁预期的旧内容,也可能发生在文件读取、工具启动或权限检查阶段。

这篇解决 codex apply_patch failed、上下文不匹配和“提示修改过了,但文件看起来没变”等问题。目标是找到失败阶段,基于文件的当前状态完成一项明确修改,并验证它确实落盘。

先按报错找到下一步

看到的现象 优先检查 下一步
Failed to find expected lines 或 Failed to find context 补丁要匹配的旧内容是否仍存在 重读目标文件,对照前后状态
文件不存在、无法读取、路径指向另一目录 工作目录、worktree、重命名与路径 先确认正确文件,再生成补丁
进程无法启动、参数或解析错误 失败的实际工具和调用阶段 缩小复现范围,保留完整诊断
明确的权限拒绝、策略或 hook 拦截 目标路径与当前生效的限制 按已授权范围处理,不绕过策略
显示成功,但目标行为没改变 实际文件内容、差异与检查结果 按第 5 步验收,不能只看成功提示

错误文本会随客户端和版本变化。apply_patch verification failed 是定位起点,不足以单独判断为 Windows 故障、换行符问题或沙箱问题。

1. 确认失败的是哪一种“应用补丁”

适用情况: 只知道“补丁失败”,还没核对工具详情。

展开失败的工具调用,记录它实际尝试了什么。三个入口需要分开:

  • Codex 的 apply_patch 工具:在任务中修改文件;遇到旧内容不匹配时,需要对照当前文件和补丁上下文。
  • CLI 的 codex apply:官方命令参考将它定义为把云端聊天的最近差异应用到本地仓库;它不是让模型重新生成一次文件修改。
  • shell 中的 git apply、GNU patch 或其他脚本:遵循各自的补丁格式、路径及冲突规则。Hunk FAILED 等文本不能直接当作 Codex 原生工具的同一种错误。

参见 Codex CLI 命令参考。如果实际失败的是 shell 命令,先保留其完整命令与退出状态,不要再套用另一种工具的修复参数。

预期结果: 能说清工具、目标路径和失败阶段。若界面只显示折叠错误,先展开详情;若调用根本没启动,就先查启动错误,而不是改文件内容。

2. 上下文不匹配:重读当前文件,不用旧内容继续试

适用情况: 工具明确报告预期旧行或上下文找不到。例如:

apply_patch verification failed:
Failed to find expected lines in <目标文件>:
<补丁预期匹配的旧内容>

先让 Codex 只读检查,明确给出失败调用里的路径:

先不要修改文件。请重新读取报错指向的目标文件及相关片段,对照失败补丁预期的旧内容,说明哪些行已不同。确认这是当前任务实际使用的文件;如果路径或内容不一致,先说明差异,不要继续套用原补丁。

随后按证据判断:

当前文件状态 如何处理 如何验证
上一轮已完成这项修改 检查结果是否已经符合目标,停止重复套用旧补丁 当前内容与预期一致,相关检查通过
编辑器格式化或其他任务改过同一片段 暂停该片段的并发编辑,让 Codex 按最新内容重做最小补丁 新补丁匹配当前内容,没有覆盖其他修改
文件被移动、重命名,或读的是另一个副本 先纠正目标路径与工作目录 实际修改出现在要使用的那份文件中
看起来相同,但仍不匹配 对比精确片段、空白、编码与换行,保留必要字节证据 找到具体差异,而不是仅凭肉眼猜测

同一补丁首次成功后,旧行可能已经被替换,再套用时找不到旧内容是合理结果。不要为了让它“再成功一次”而撤销正确修改。

预期结果: 找到当前内容与预期旧内容的差异;下一次补丁基于刚刚读取的状态。若仍失败,保存这次重新读取后的文件状态和新错误,进入第 4 步做最小范围验证,不在长对话中原样重试。

3. 路径或文件状态不对:确认实际工作树

适用情况: 文件不存在、文件内容与编辑器所见不同,或在多项目、worktree、远程环境中工作。

在失败命令的实际环境、目标 Git 仓库中运行以下读取命令。占位路径替换为目标文件相对该仓库的路径:

git rev-parse --show-toplevel
git --no-optional-locks status --short
git diff -- "路径/目标文件"
git diff --cached -- "路径/目标文件"

预期结果: 仓库顶层、目标文件和本次任务使用的位置一致,已暂存与未暂存的差异能够分别解释。状态中的 ?? 是未跟踪文件,其正文不会出现在普通 git diff 中,要单独打开查看。非 Git 项目则直接核对实际目录、文件内容和修改前副本。

如果 Codex 在 WSL、SSH、容器或独立 worktree 中执行,本机编辑器里的同名文件不一定是它正在修改的对象。先参考 worktree 改动位置排查,不要把一份文件直接覆盖到另一份来消除差异。

换行与编码也应按证据处理。发现 CRLF 文件不等于找到了根因,更不需要统一整个仓库的换行符。若修改后出现大量无关行变化,先核对项目规范和实际字节变化,再决定如何保留原格式。

4. 区分内容错误、工具异常与写入拒绝

适用情况: 已确认当前文件,但补丁仍无法执行。

先把任务缩到一个文件、一个已确认片段。可以这样要求 Codex:

请基于刚刚读取的内容,只完成已经确认的这一处修改。保留其他改动和文件格式。若上下文再次不同,停止写入并重新读取;若工具启动、解析或权限检查失败,报告该阶段的完整错误,不把整份文件重写作为默认补救。

上下文或补丁格式错误: 检查新补丁是否针对当前文件、是否包含有效的修改内容。模型产生的格式错误应修正后再试;不需要为此在系统里另装一个名字相同的 apply_patch 程序。

启动、参数或平台相关错误: 记录客户端、版本、系统、执行主机、错误发生时间及最小修改范围。只有大段修改失败而小段成功时,可以保留这条对比证据并分段审查;它仍不能独自证明是某个参数长度限制。旧 issue 中某个版本的 Windows 解法,不应成为所有用户的通用降级或替换工具建议。

权限、策略或 hook 明确拒绝: 读取拒绝原因及目标路径,再核对当前会话状态。当前 CLI 可用 /status、/debug-config 查看状态与配置来源;不可用时以该版本的帮助和客户端界面为准。官方 Hooks 文档说明,PreToolUse 可以拦截 apply_patch 文件修改,因此不是所有拒绝都来自补丁内容。

若确需修改受限路径,按现有组织策略确认必要授权;不要关闭全部 hooks、扩大所有目录权限,或改用 shell 来绕过同一条限制。拒绝发生在 Git 元数据时,转到 index.lock 与 Git 提交权限排查。

验证目标: 一次只处理已确认的原因,再观察同一项目标修改。如果工具连最小修改也无法执行,保留最小案例与错误求助,不继续扩大修改范围。

5. 修改后,用文件、差异和检查结果验收

适用情况: 工具已返回成功,准备判断是否真正完成。

先打开实际目标文件,确认需要的内容确实存在。Git 仓库继续检查:

git --no-optional-locks status --short
git diff --stat
git diff -- "路径/目标文件"
git diff --cached -- "路径/目标文件"
git diff --check

逐项确认:目标路径正确、差异对应本次需求、没有无关整文件重写、已有用户改动仍在。新建且未跟踪的文件需另外查看正文;不要仅为显示 diff 就把全部文件暂存。

git diff --check 用于检查空白错误,不能证明业务逻辑正确;其提示也要结合仓库既有格式规范解释,不能据此断言补丁没有落盘。然后运行该项目与修改相关的测试、类型检查或其他验收步骤。可参考 代码审查工作流。Git 的 状态与 差异参考解释了这些检查范围。

OpenAI 的编码提示指导也要求验证实际修改,不能仅凭工具的“Done”或模型的完成声明判断成功。对重复重试的任务,还要检查是否产生了重复插入或已经完成的修改。

仍失败时,提交一个能看懂的最小案例

提供工具名称、失败阶段、客户端和版本、执行环境、脱敏路径,以及必要的前后片段。说明重读后的最小修改是否仍失败、文件是否已部分改变。不要附上整份私有项目、完整环境变量或认证文件。

若失败发生在非交互脚本,继续查 codex exec 无输出与异常退出;定时任务里未发生预期修改时,先核实 计划是否真正执行。

本文于 2026-10-17 核对官方资料,并在独立测试仓库验证原生补丁工具的上下文失配、失败后原字节保持、修正后目标内容和 CRLF 文件结果,以及成功补丁再次应用的合理失败。验证没有调用模型,没有复现所有客户端或 Windows 工具启动故障;实际修复仍需以当前错误和文件结果为准。

社区讨论

补充你的经验或问题

评论由 GitHub Discussions 承载;参与讨论需要登录 GitHub。