macOS 0.122.0: apply_patch hangs under workspace-write but succeeds under danger-full-access

Open 💬 7 comments Opened Apr 22, 2026 by andrewalex
💡 Likely answer: A maintainer (github-actions[bot], contributor) responded on this thread — see the highlighted reply below.

Summary

On macOS ARM64 with codex-cli 0.122.0, the internal apply_patch tool can hang indefinitely under the normal sandboxed path (workspace-write / --full-auto) on a tiny local file.

The same exact patch succeeds immediately when the nested Codex run uses --dangerously-bypass-approvals-and-sandbox (danger-full-access).

This looks distinct from #17834:

  • #17834 is the earlier macOS 0.120.0 case where apply_patch returned a ~10s timeout with exit code 124
  • this report is the newer 0.122.0 case where apply_patch is dispatched but then produces no success or error until interrupted/killed

Environment

  • OS: macOS 26.3.1 (build 25D771280a)
  • Arch: arm64
  • Codex CLI: codex-cli 0.122.0

Minimal repro

mkdir -p /tmp/codex-test
printf 'one\ntwo\n' > /tmp/codex-test/test.txt

Interactive repro:

cd /tmp/codex-test
codex

Then ask Codex:

use apply_patch to change "two" to "three" in test.txt

Non-interactive repro for the same sandboxed path:

codex exec --json --full-auto --skip-git-repo-check --cd /tmp/codex-test \
  'use apply_patch to change "two" to "three" in test.txt'

Observed behavior under workspace-write

Codex reads test.txt, emits the apply_patch tool call for the expected one-line diff, and then nothing comes back from the tool path.

The patch used was:

*** Begin Patch
*** Update File: test.txt
@@
-two
+three
*** End Patch

Observed outcome:

  • no success output
  • no parse error
  • no deterministic tool error
  • file remains unchanged
  • the session only ends after manual interrupt or an external timeout wrapper kills the run

In a fresh batch I ran the same --full-auto repro 5 times with an outer 45-second wrapper. Results:

  • 0/5 succeeded
  • 5/5 hung until killed by the wrapper
  • 5/5 left test.txt unchanged as:
one
two

Comparison against danger-full-access

Running the same repro with:

codex exec --json --dangerously-bypass-approvals-and-sandbox --skip-git-repo-check --cd /tmp/codex-test \
  'use apply_patch to change "two" to "three" in test.txt'

succeeded immediately with normal tool output:

Success. Updated the following files:
M /tmp/codex-test/test.txt

and the file became:

one
three

Why this seems important

This strongly suggests the problem is in the sandboxed filesystem / helper path used by apply_patch, not in the patch text itself. That is an inference from the behavior above, not a confirmed root cause.

Expected behavior

The same minimal patch should either:

  • succeed normally under workspace-write, or
  • fail quickly with a deterministic tool error

It should not hang indefinitely on a 2-line local file.

Related

  • Related but distinct: #17834

If useful, I can provide redacted session JSONL excerpts showing the workspace-write hang and the danger-full-access success.

View original on GitHub ↗

7 Comments

github-actions[bot] contributor · 2 months ago

Potential duplicates detected. Please review them and close your issue if it is a duplicate.

  • #17834

Powered by Codex Action

andrewalex · 2 months ago

Follow-up data point from the same minimal /tmp/codex-test repro on the same machine.

I reran the nested danger-full-access / --dangerously-bypass-approvals-and-sandbox path 5 more times with the same patch and a 45-second outer wrapper.

Results:

  • 5/5 succeeded
  • 0/5 hung
  • 5/5 changed test.txt from:
one
two

to:

one
three

Durations were roughly 17-21 seconds per run.

So the current local split is:

  • workspace-write: 0/5 success, 5/5 hang
  • danger-full-access: 5/5 success, 0/5 hang

That still points at the sandboxed path as the differentiator rather than the patch text itself.

etraut-openai contributor · 2 months ago

Do you have reason to believe that this behavior changed recently? I'm trying to determine if it's a regression.

andrewalex · 2 months ago
Do you have reason to believe that this behavior changed recently? I'm trying to determine if it's a regression.

Good question. On April 14th, I'd primarily get timeouts (Issue #17834) now I get complete hangs, so I'd say it's gotten worse and its become more predictable.

etraut-openai contributor · 2 months ago

We haven't had other reports of #17834 or this issue, so I'm wondering if this is something that's specific to your machine. It's unlikely we'll be able to prioritize an investigation unless this is reported by other users. Since codex is open source, you could clone the repo and work with Codex to try to identify a root cause.

andrewalex · 2 months ago

I found two concrete issues in the macOS sandboxed fs-helper path:

  1. In codex-rs/utils/absolute-path/src/lib.rs, AbsolutePathBuf was calling home_dir() even for ordinary absolute paths like /tmp/.... That should only happen for ~ paths.
  2. In codex-rs/exec-server/src/fs_sandbox.rs, the fs-helper is launched with env_clear() and a very small allowlist, which drops __CF_USER_TEXT_ENCODING on macOS.

__CF_USER_TEXT_ENCODING is a private macOS/CoreFoundation env var associated with per-user text encoding state (~/.CFUserTextEncoding`).

In the sampled blocked stacks, both of those led into the same Apple fallback path (getpwuid_r -> notify_register_check -> bootstrap_look_up2) inside the sandboxed fs-helper. That helper path is not used under YOLO, which explains why it works. On my machine, that fallback path can block. On other machines it may return quickly, which would explain why this can be a real code-level bug but still only show up for one reporter so far.

I patched both locally:

  • preserve __CF_USER_TEXT_ENCODING for the macOS fs-helper
  • skip home_dir() lookup unless the path actually starts with ~

I also added regression coverage for the non-~ path case.

I couldn’t open a PR because this repo currently restricts PR creation, but I pushed a branch to my fork in case its useful.

andrewalex · 2 months ago

@etraut-openai Any chance we can get this fix into an upcoming version? Both changes are contained and quality improvements on their own even without this bug