TUI freeze after submitting `/side` (intermittent): recurring `sleep 180` sandbox respawns block main thread

Open 💬 1 comment Opened May 17, 2026 by divinequest

Summary

In codex-cli 0.130.0 (Linux, npm-installed), submitting /side intermittently deadlocks the TUI. When the freeze happens, the CLI has spawned a sandboxed bash -c 'sleep 180' via bwrap, the main input thread blocks synchronously on that exec, and the sandbox respawns immediately when each 3-minute sleep ends — so the TUI never recovers without killing the codex process.

/side does not always freeze: same user, same machine, sometimes opens a working side-thread, sometimes deadlocks. When it freezes, subsequent /side attempts also freeze and stack additional sleep 180 processes under separate bwrap chains.

Reproduced twice in two separate codex resume invocations on the same machine within ~30 minutes.

Environment

  • codex-cli 0.130.0 (npm-installed at ~/.npm-global/bin/codex)
  • Linux 6.8.0-1052-aws, x86_64
  • bash 5.x, tmux 3.2a host shell
  • bwrap (bubblewrap) sandbox enabled
  • No custom ~/.codex/config.toml overrides for sandbox/network

Repro (intermittent)

  1. Launch codex resume in a tmux pane.
  2. Type /side in the compose buffer.
  3. Press Enter to submit.
  4. Sometimes the side-thread opens normally and is usable. Other times the TUI freezes: the side-thread sandbox spawns a bash -c 'sleep 180', the main input thread blocks synchronously on that exec, the footer status stops ticking, and no keystrokes (Esc / Ctrl-C / Backspace via tmux send-keys) get processed.
  5. After 180s the sleep ends, a fresh sandbox respawns under a new bwrap chain within ~1s, and the cycle repeats indefinitely. Issuing additional /side invocations during the freeze stacks more concurrent sleep 180 processes.

Expected

  • Submitting /side should always open a responsive side-thread.
  • The sandboxed shell that backs the side-thread should run as a background task so the main TUI stays interactive (current Esc / Ctrl-C / /quit should work even while the sandbox is running).
  • A side-thread that fails to initialise should error visibly rather than silently spinning a 180-second-sleep loop.

Actual

  • Each freezing /side invocation spawns this process chain:

``
codex resume
└─ codex-linux-sandbox --sandbox-policy-cwd ... --command-cwd ...
└─ bwrap --new-session --die-with-parent ...
└─ bwrap (inner)
└─ bash -c 'sleep 180'
``

  • Three concurrent sleep 180 processes were observed across panes, each parented to a separate sandbox chain, after stacking multiple /side attempts during a freeze.
  • When one sleep 180 exits, a fresh one spawns within <1s under a new bwrap chain — render-loop-style respawn rather than a single one-shot warmup.
  • ps -o etimes showed the sleep 180 PIDs continuously rolling over (e.g. 113s elapsed → killed → new one at 0s).
  • Pane stays at the same frozen TUI frame the entire time:

```
◦ Working (28m 01s • esc to interrupt)

› /side

/side start a side conversation in an ephemeral fork
```

Diagnostic evidence

ps chain at one capture:

PID    PPID   ETIME  CMD
1394741  ...    ...   .../codex/codex resume
1411822 1394741 01:33 codex-linux-sandbox --sandbox-policy-cwd ...
1411826 1411822  ...  bwrap --new-session --die-with-parent ...
1411827 1411826  ...  bwrap (inner)
1411828 1411827 01:53 sleep 180

After killing the inner sleep 180, two new sleep 180s (PIDs 1413278, 1413297) appeared under fresh bwrap chains within seconds.

Workaround

  • kill -INT <codex-resume PID> exits the CLI cleanly and frees the pane. Any background work the agent had launched via SSH/tmux on remote machines continues uninterrupted (that's not the same as the local bwrap sandbox).
  • Once the TUI is frozen, /side keystrokes typed via tmux send-keys do not unfreeze it.

Likely root cause (speculative)

The sleep 180 looks like a "hold this sandboxed shell alive long enough for the side-thread to use it" mechanism. The intermittent nature suggests a race condition rather than a deterministic bug — possibly:

  1. The exec is run synchronously on the TUI's main input thread instead of a background task whenever the side-thread sandbox warmup happens to hit a slow path.
  2. There's a sandbox-setup retry/respawn loop that fires when the initial spawn doesn't complete a handshake in time, and once it gets into that loop the main thread never gets to drain the side-thread output that would tell it the sandbox is ready.

Either way the user-visible symptom is the same: TUI is unrecoverable until the process is killed.

Why this matters in practice

Both Codex CLI sessions where this reproduced had been driving long-running training/eval workflows for many hours. The freeze itself is recoverable (SIGINT + codex resume restores the conversation), but the pattern is hostile to unattended/overnight use — the agent's TUI silently freezes for tens of minutes whenever /side happens to hit the bad path, and the user has no visible signal that the sandbox loop is the cause.

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗