Frequent apply_patch failures after 0.117.0 appear to come from the execution/runtime path, not from patch grammar parsing

Open 💬 2 comments Opened Mar 28, 2026 by jasontan656

What version of Codex CLI is running?

117

What subscription do you have?

200usd

Which model were you using?

gpt 5.4

What platform is your computer?

_No response_

What terminal emulator and version are you using (if applicable)?

_No response_

What issue are you seeing?

Title
Frequent apply_patch failures after 0.117.0 appear to come from the execution/runtime
path, not from patch grammar parsing

Session Reference
Codex session id: "019d310c-4996-7d52-b3e6-67a59ad0d0ad"

Summary
After upgrading to codex-cli 0.117.0, I started seeing apply_patch fail much more
frequently than before.

After reviewing the target session log and the current open-source Codex code, my
conclusion is:

  • This does not look like a primary apply_patch parser/grammar regression.
  • It looks much more like an execution-path regression around the runtime/delegation layer

that actually runs the verified patch.

  • The timing strongly overlaps with 0.117.0 changes that made the app-server TUI default

and refactored execution/environment handling through exec-server abstractions.

Why I do not think this is mainly a patch grammar problem
In the referenced session, the failures are not all the same kind.

I found at least three distinct failure classes:

  1. Invalid patch target type

The session attempted to patch a compiled .pyc file under __pycache__, which failed
with:
stream did not contain valid UTF-8

That is not a parser regression. That is a bad patch target.

  1. Invalid patch body

The session also produced:
apply_patch verification failed: invalid hunk at line 4, Update hunk does not contain
any lines

This matches current open-source parser behavior exactly. The parser still explicitly
rejects empty update hunks.

  1. Execution-layer ENOENT

The most interesting failures were repeated:
execution error: Io(Os { code: 2, kind: NotFound, message: "No such file or
directory" })

These happened after the patch had already been parsed and verified well enough to
construct a changes payload. That strongly suggests the failure happened after
verification, during actual patch execution.

This is the key reason I do not think the main issue is grammar parsing.

What looks more likely
Current open-source Codex still routes apply_patch through a verify-then-delegate model:

  • the patch is parsed and verified first
  • then the runtime delegates execution by re-invoking Codex itself using:

codex --codex-run-as-apply-patch <patch>

Relevant source files:

  • codex-rs/core/src/tools/handlers/apply_patch.rs
  • codex-rs/core/src/tools/runtimes/apply_patch.rs
  • codex-rs/arg0/src/lib.rs
  • codex-rs/apply-patch/src/parser.rs
  • codex-rs/apply-patch/src/lib.rs

This means apply_patch is more sensitive than a normal file write to issues in:

  • executable path resolution
  • self-reexec program path
  • app-server / exec-server environment handoff
  • sandbox command construction
  • cwd/path canonicalization
  • wrapper / dispatch behavior

If any of those drift, apply_patch can still pass verification and then fail later with
ENOENT during execution.

Why 0.117.0 is suspicious
The timing lines up with two important upstream changes:

  1. App-server TUI enabled by default

PR: #15661 “Enable tui_app_server feature by default”
https://github.com/openai/codex/pull/15661

  1. Exec/environment refactors just before that

PR: #15125 “Move environment abstraction into exec server”
https://github.com/openai/codex/pull/15125

PR: #15232 “Refactor ExecServer filesystem split between local and remote”
https://github.com/openai/codex/pull/15232

PR: #15233 “Split exec process into local and remote implementations”
https://github.com/openai/codex/pull/15233

Those changes are much closer to the observed symptom than any parser-specific change.

What I did not find
I did not find evidence that 0.117.0 introduced a major parser tightening for apply_patch.

In fact, the parser still appears lenient:

  • PARSE_IN_STRICT_MODE = false
  • earlier upstream changes even relaxed patch marker handling rather than tightening it

I also checked a recent apply_patch-related PR in the 0.117 window:

  • PR #15100 “Add apply_patch code mode result”

https://github.com/openai/codex/pull/15100

That change affects result surfacing/output behavior, not parser semantics or patch file
application logic.

Important session-specific observation
In the target session, some failing patch attempts were followed by shell checks showing
that the target file still existed and was visible from the expected path.

That makes the repeated ENOENT even more suspicious as an execution-path problem rather
than a missing target file problem.

There was also visible runtime surface drift in the same session:

  • old Python-oriented skill entry surfaces were still being read
  • new TypeScript-oriented runtime files were being generated

I do not think the TypeScript migration itself is the root cause, but it may have
increased the chance of exposing an execution-path bug.

Likely root-cause direction
My current best hypothesis is:

apply_patch became more failure-prone in 0.117.0 because the runtime path that delegates
verified patches into actual execution changed, likely due to app-server / exec-server
default-path changes, and not because patch syntax validation became stricter.

  • whether sandbox/path canonicalization causes the delegated executable or working

directory to become unresolved

Short conclusion
This looks like an apply_patch execution/runtime regression, not primarily a parser
regression.

The strongest signal is that the session contains repeated post-verification ENOENT
failures, while current open-source parser behavior remains broadly lenient and unchanged
in the ways that would explain this pattern.

What steps can reproduce the bug?

Uploaded thread: 019d33a5-9976-73f3-b05f-6fb0802c5c13
Codex issue session id: "019d310c-4996-7d52-b3e6-67a59ad0d0ad"

What is the expected behavior?

_No response_

Additional information

_No response_

View original on GitHub ↗

This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗