apply_patch sometimes invoked as shell command -> 'apply_patch: command not found'

Open 💬 17 comments Opened Aug 12, 2025 by vitatea2023
💡 Likely answer: A maintainer (bolinfest, collaborator) responded on this thread — see the highlighted reply below.

@bolinfest @gpeal @pakrym-oai @dylan-hurd-oai

What version of Codex is running?
Built from source at commit cb78f23 (local copy).

Which model were you using?
Observed when assistant outputs resembling gpt-4.1 style tool calls; the bug is about how assistant-generated apply_patch invocations are parsed/handled by Codex regardless of model.

What platform is your computer?
Linux 6.14.3-x86_64-linode168 x86_64 unknown

Steps to reproduce

  1. Have the assistant produce a shell/tool call that embeds an apply_patch invocation in a shell script. Example variants that can trigger the issue:
  • {"command": ["apply_patch", "<<'EOF'\n*** Begin Patch\n*** Update File: README.md\n@@\n- old\n+ new\n*** End Patch\nEOF\n"]}
  • {"command": ["bash","-lc","cd repo && apply_patch <<'EOF'\n*** Begin Patch\n*** Update File: README.md\n@@\n- old\n+ new\n*** End Patch\nEOF\n"]}
  1. Codex attempts to execute the tool call. If the invocation is not recognized by the maybe_parse_apply_patch detection logic, the runtime will spawn the requested shell command literally.
  2. Since apply_patch is a virtual tool implemented inside the Codex binary (invoked via --codex-run-as-apply-patch), there is no apply_patch binary on PATH, so bash reports:

bash: line N: apply_patch: command not found

Expected behavior

  • Codex should robustly detect apply_patch invocations (including heredoc forms and when apply_patch is not at the start of the script) and either: (A) handle the patch programmatically, or (B) exec the Codex binary with --codex-run-as-apply-patch <patch> so the virtual tool runs — instead of running the shell which will try to find a real apply_patch binary.

Actual behavior

  • In some model-generated cases the detection logic misses the apply_patch invocation (examples: scripts that include cd && apply_patch <<'EOF', other shells like sh -lc, or different command-name spellings like apply-patch). The fallback is to spawn the shell literally, which leads to apply_patch: command not found.

Relevant code pointers

  • Detection/parsing: codex-rs/apply-patch/src/lib.rs (maybe_parse_apply_patch, extract_heredoc_body_from_apply_patch_command)
  • Patch parsing: codex-rs/apply-patch/src/parser.rs
  • Replacement exec: codex-rs/core/src/codex.rs (creates exec with --codex-run-as-apply-patch when a patch is recognized)
  • Spawn/exec: codex-rs/core/src/exec.rs and codex-rs/core/src/spawn.rs

Suggested fixes / mitigation

  • Relax the initial check in extract_heredoc_body_from_apply_patch_command (it currently requires the script to start with apply_patch) and instead traverse the AST to find any apply_patch invocation and extract its heredoc body.
  • Accept more shell invocation forms (e.g. sh -lc) and common command-name variants (e.g. apply-patch) or normalize names in detection.
  • Add a pre-spawn, permissive check: if any element of params.command contains apply_patch/applypatch/<<EOF etc., try to parse it as a patch before actually spawning.
  • Add unit tests that cover realistic failing variants (e.g., cd && apply_patch <<'EOF' and sh -lc forms).

Additional notes
This is a reliability/usability issue that causes noisy user-visible errors when the model's generated tool call is syntactically different from the narrow forms currently recognized. Improving detection should reduce these failures.

View original on GitHub ↗

17 Comments

vitatea2023 · 11 months ago

Note: This issue (including the analysis, examples, and suggested fixes) was generated automatically by Codex and has NOT been human-reviewed. It may contain inaccuracies, omissions, or incorrect assumptions.

Please treat the reproducer and remediation suggestions as preliminary: verify the reproduction steps and the diagnosis before acting.

If helpful, I can provide a minimal repro script, run logs, or submit a preliminary PR that implements a targeted mitigation (e.g. more permissive detection of apply_patch heredocs). Please let me know which would be most useful.

vitatea2023 · 11 months ago

Note: This comment was generated automatically by Codex and has NOT been human-reviewed. Please verify the content before acting on it.

This snippet is intended to be added to the repository's AGENTS.md so that Codex will load it on startup; it contains a focused apply_patch section only. This snippet may help mitigate the issue described above, but please validate before relying on it.

### apply_patch — REQUIRED (important)

- Virtual tool: `apply_patch` is implemented inside the Codex executable (invoked via `--codex-run-as-apply-patch`). There is no standalone `apply_patch` binary on `PATH`.

- Preferred invocation (structured command array):
  - `["apply_patch", "*** Begin Patch\n*** Update File: path/to/file\n@@\n- old\n+ new\n*** End Patch\n"]`
  - Explanation: pass the full patch text as the second element (including `*** Begin Patch`/`*** End Patch`).

- If you must use a heredoc, wrap it with `bash -lc` so the runner interprets the heredoc as shell would:
  - `["bash","-lc","apply_patch <<'EOF'\n*** Begin Patch\n...\n*** End Patch\nEOF\n"]`
  - Avoid passing the heredoc markers as a literal argv string (e.g. `["apply_patch","<<'EOF'...EOF"]`) because that may be interpreted literally and is not reliably parsed.

- Command name variants: do not use `apply-patch` (with a hyphen) or other unapproved variants; detection expects `apply_patch` (and in limited cases `applypatch`).

- If you need to run a small script that includes `apply_patch` (for example `cd repo && apply_patch <<'EOF'...EOF`), prefer wrapping the entire script in `bash -lc`, or pass the patch text directly as the second argument.
xdnlprs · 11 months ago

It seems to happen almost on every session for me. It will first try it wrongly, then it realizes it got it wrong and from then on it uses the tool correctly.

A bit of a waste of time, context and money.

bolinfest collaborator · 10 months ago

@vitatea2023 @xdnlprs I believe https://github.com/openai/codex/pull/2646 should fix the issue, which was available starting in https://github.com/openai/codex/releases/tag/rust-v0.24.0.

Does this fix your issue?

sebthom · 10 months ago

I have this issue in 0.31.0 like that: /c/scoop/apps/git-with-openssh/current/usr/bin/bash: line 1: applypatch: command not found

creatorrr · 10 months ago

same... here's a snippet:

• Ran
  └ apply_patch << 'PATCH'
    *** Begin Patch
    *** Update File: docs/CONTAINER_PUBLISHING.md
    @@
     ### Running Containerd Image
    @@
     ```bash
     # Run rootless containerd
     docker run -d \
       --name mem-mcp-containerd \
       --security-opt apparmor=unconfined \
       --security-opt seccomp=unconfined \
       --device /dev/fuse \
    -  -p 8000:8000 \
    +  -p 8000:8000 \
       -v mem-data:/data \
       ghcr.io/julep-ai/mem-mcp-containerd:latest
     ```
    +
    +Note: The macOS launcher defaults to host port 6366 → container 8000 (`-p 6366:8000`). Examples
        above use `8000:8000` for direct runs without the launcher.
    *** End Patch
    bash: line 21: warning: here-document at line 1 delimited by end-of-file (wanted `PATCH')
    bash: line 1: apply_patch: command not found

⠙ Running
  └ python - << 'PY'
    from pathlib import Path
    p=Path('docs/CONTAINER_PUBLISHING.md')
    s=p.read_text()
    needle='ghcr.io/julep-ai/mem-mcp-containerd:latest\n````'
    if 'macOS launcher defaults to host port' not in s:
        s=s.replace('ghcr.io/julep-ai/mem-mcp-containerd:latest\n```','ghcr.io/julep-ai/
        mem-mcp-containerd:latest\n```\n\nNote: The macOS launcher defaults to host port 6366 → container
        8000 (`-p 6366:8000`). Examples above use `8000:8000` for direct runs without the launcher.')
    Path('docs/CONTAINER_PUBLISHING.md').write_text(s)
    print('CONTAINER_PUBLISHING updated')
    PY
keen99 · 10 months ago

same - this happens a lot:

• Ran
  └ apply_patch << 'PATCH'
    *** Begin Patch
...
    *** End Patch
    /opt/homebrew/Library/Homebrew/cmd/shellenv.sh: line 27: /bin/ps: Operation not permitted
    bash: line 85: warning: here-document at line 1 delimited by end-of-file (wanted `PATCH')
    bash: line 1: apply_patch: command not found

the most fun part is sometimes it doesnt notice it didnt work, so it acts like it was completed...and then it's 2 or 3 more messages before it finally does the work.

riatzukiza · 10 months ago

Yeap... it does this a lot... some times it tries to run applypatch. I was having problems with it on my system cause that was an actual program (from the makepatch package in ubuntu apt) and it would pass and codex would think he was successfully applying patches then to use an LSP server tool I make him use to check if he actually fixed the errors I asked him to fix, for him to find nothing changed. Then he'd go and try the same tool again...

I've since uninstalled the package makepatch that added applypatch
My solution for most sessions is to tell it to use the filesystem mcp tool I set up in it's environment.

0xdevalias · 9 months ago

Just ran into another variation of this issue, where it tries to call /usr/bin/apply_patch, and the path prefix means that the TUI hook doesn't catch it:

• Proposed Command
  └ /usr/bin/apply_patch <<'PATCH'
    *** Begin Patch
    ..snip..
rogeralsing · 9 months ago

I see the exact same error in my hobby project agent.
when using the gpt-5-codex model, I have my own command tool schema for executing commands, but it does indeed believe that apply_patch is a native command.

It seems to me, as if the gpt-5-codex model has been trained to know about built in Codex agent commands, since it´s replicated completely outside of the codex agent itself, just using the model.

I might be wrong, but it´s the reason I found this issue.

cratexnet · 9 months ago

This issue still exists in the latest version 0.46.

bolinfest collaborator · 9 months ago

apply_patch should always be invoked as a shell command.

Here is the logic where we modify the PATH such that it should be available:

https://github.com/openai/codex/blob/fc1723f13185a06e29ee263c05b6e0750024daaf/codex-rs/arg0/src/lib.rs#L82-L90

Are you using Codex in a bespoke way that would avoid that setup?

originell · 8 months ago

i also just ran into this. I am running the fish shell and launching codex via a custom command:

function cdx
   codex \
       -m gpt-5-codex --yolo \
       --enable web_search_request \
       $argv
end
szerintedmi · 8 months ago

this happens to me recently more often (codex max) and fails very often due to incorrect syntax.
even the retries often fail after the first failure.

It is generating long agent loops for the most simple file edits.

% codex --version
codex-cli 0.61.0

vscode codex plugin version: 0.4.46

<img width="559" height="481" alt="Image" src="https://github.com/user-attachments/assets/76984e90-aa09-4616-835f-9009dfba274c" />

Acters · 8 months ago

Ran into this while using codex max. I stopped it, and told it to stop running apply_patch as a cli tool and stop using bash. I told it that it is running inside a codex cli environment. At least that stopped it for now.

Simply ridiculous behavior, I hope openAI fixes it.

yuvrajangadsingh contributor · 6 months ago

Hi @bolinfest, I noticed this issue is still affecting users on recent versions despite the PATH fix in #2646.

I've opened a PR to address the remaining edge cases: #9498

The fix handles:

  • /usr/bin/apply_patch (absolute path prefix)
  • ./apply_patch (relative path prefix)
  • apply-patch (hyphenated variant)
francescobianco · 1 month ago

For Linux environments, please consider using RAP:
https://github.com/francescobianco/rap

It provides a more reliable patch application workflow and helps avoid issues related to apply_patch behavior and sandbox/environment inconsistencies.