[macOS Desktop] functions.exec cell never settles after nested tool completes

Open 💬 1 comment Opened Aug 26, 2026 by fongryan

Summary

On Codex Desktop for macOS, an outer functions.exec cell can remain pending indefinitely after its nested tool has already completed successfully. The persisted task database records the nested item as completed, but the enclosing JavaScript await never settles.

This is a current macOS reproduction of the post-tool-result stall class previously described in #24738, which the original reporter self-closed.

Environment

  • macOS, Apple Silicon
  • Codex Desktop: 26.818.61809 (build 7019)
  • Primary runtime bundle: 26.819.11345
  • Dynamic tool registry during the live repro: 312 tools
  • The defect reproduced with third-party claude-mem tools absent

Minimal live reproduction

  1. Start a functions.exec cell that sequentially awaits:
  2. nested exec_command running /usr/bin/true
  3. workspace dependency discovery
  4. a GitHub fetch
  5. The outer cell yields after 30 seconds with Script running with cell ID ....
  6. Wait another 60 seconds, then another 120 seconds.
  7. The cell remains pending for more than 211 seconds.
  8. Inspect the task's persisted thread_items row for the first nested call.

Persisted result:

rollout_ordinal: 727
command: /bin/zsh -c /usr/bin/true
status: completed
exit_code: 0
duration_ms: 0

The second and third nested calls are never reached because the first await never settles.

After terminating only the enclosing cell, a fresh nested exec_command querying the database completes in 0.3 seconds. This shows that the shell and tool worker are healthy; the lost signal is between the completed nested item and the enclosing orchestration promise.

Cross-tool evidence

During earlier occurrences in the same task, all of these appeared hung to the outer cell but were persisted as completed:

  • local commands: exit code 0, 0–1092 ms
  • workspace dependency discovery: 22 ms
  • GitHub fetch: 868 ms and 1166 ms
  • context search: 1056 ms

Pure JavaScript inside functions.exec still completed immediately.

Cancellation leak

A controlled test found that terminating an outer cell awaiting nested exec_command("/bin/sleep 15") did not cancel the nested process. pgrep still showed the wrapper and /bin/sleep 15; persisted history later recorded the command completing after 14,868 ms.

Repeated terminate-and-retry therefore leaves nested work behind and may increase bounded-worker or queue pressure.

Desktop log evidence

The same desktop session contains:

mcp_request_timeout ... pendingCount=5 ... timeoutMs=30000

The request later routed successfully at 31.9 seconds. The log also repeatedly records:

Received turn/started for unknown conversation
Received item/started for unknown conversation
Received item/completed for unknown conversation

Those unknown-conversation events referenced another active task, so they are correlation rather than the exact dropped callback. They point toward the conversation/turn/item event-correlation layer during concurrent task restoration.

Expected behavior

  • A completed nested result promptly settles the enclosing functions.exec promise.
  • If forwarding fails, the outer cell surfaces a bounded error rather than pending forever.
  • Terminating the outer cell cancels or safely detaches nested requests and cleans up local children.

Actual behavior

  • Nested item completes and is persisted successfully.
  • Enclosing await never settles.
  • The cell remains pending indefinitely.
  • Termination does not propagate to a still-running nested process.

I can provide additional redacted SQLite queries and timestamp extracts if needed.

View original on GitHub ↗

1 Comment

fongryan · 2 days ago

Post-update verification on macOS:

  • Desktop updated from 26.818.61809 (build 7019) to 26.820.60940 (build 7119).
  • Primary runtime remains the current bundled runtime line.
  • The exact minimal nested-forwarding probe settled successfully: nested /usr/bin/true returned exit code 0 and the enclosing functions.exec cell completed in 107 ms.
  • Stress sample: 20 sequential nested /usr/bin/true calls inside one enclosing cell all settled; min 87 ms, max 257 ms, total 2709 ms.
  • Cross-backend sample in one enclosing cell also settled: workspace dependency discovery 19 ms; GitHub fetch 621 ms; total 641 ms.

This is a green post-update sample, not proof that the intermittent defect is permanently fixed. The pre-update live repro remains valid: the same minimal nested call had been persisted completed in 0 ms while its enclosing cell stayed pending for more than 211 seconds.

The one-shot relaunch helper and launchd job were removed after verification.