Skip to content

Conversation

@ethanndickson
Copy link
Member

@ethanndickson ethanndickson commented Dec 29, 2025

Problem

When a subagent calls agent_report, a race condition causes spawn bash ENOENT errors on Linux (and likely other platforms).

Error seen:

RuntimeError: Failed to execute command: spawn bash ENOENT
    at ChildProcess.<anonymous> (.../LocalBaseRuntime.ts:138:16)

This looks like bash isn't found, but the real issue is Node.js reporting ENOENT when the cwd doesn't exist (misleading error).

On Linux, this would produce a popup containing the error.

Root Cause

Race between frontend git status polling and backend workspace deletion:

  1. Subagent calls agent_report → backend starts remove()
  2. remove() adds workspaceId to removingWorkspaces set
  3. remove() deletes workspace directory from disk
  4. Frontend's in-flight executeBash IPC arrives (started before removal)
  5. executeBash spawns bash with the deleted cwd → ENOENT

The race is consistent because agent_report triggers a metadata update with taskStatus: "reported", which the frontend receives and triggers an immediate git status refresh - right as the backend is deleting the directory.

Fix

Add a removingWorkspaces guard to executeBash. The removingWorkspaces set is populated for the entire duration of remove() (set at start, cleared in finally block), so any bash execution attempt during removal returns Err("Workspace is being removed").

This is the holistic fix point:

  • All bash execution flows through executeBash
  • The guard covers the full removal window (disk delete → config remove → metadata emit)
  • Frontend already handles Err results gracefully

Why not reorder remove() to invalidate before deleting?

The original disk-first ordering provides atomicity: if disk deletion fails (and force=false), we abort and keep the workspace in config so the user can retry. Invalidating first would risk orphaned directories that users can't manage.


Generated with mux • Model: anthropic:claude-opus-4-5 • Thinking: high

When a subagent calls agent_report, the backend deletes its workspace
directory. A race condition occurs because the frontend's GitStatusStore
may have an in-flight executeBash call for that workspace:

1. Subagent reports → backend starts remove()
2. remove() deletes directory from disk
3. Frontend's executeBash arrives, tries to spawn bash with deleted cwd
4. Node.js reports 'spawn bash ENOENT' (misleading - cwd is gone, not bash)

The fix adds a removingWorkspaces guard to executeBash. This set is
populated for the entire duration of remove(), so any bash execution
attempt during removal returns Err('Workspace is being removed').

This is the holistic fix point - all bash execution flows through
executeBash, and the guard covers the full removal window (disk delete
through metadata emit).

We preserve the original disk-first ordering in remove() to maintain
atomicity: if disk deletion fails (and force=false), we abort and keep
the workspace in config so the user can retry. Reordering to invalidate
first would risk orphaned directories on disk.
@ethanndickson ethanndickson force-pushed the ethan/fix-subagent-bash-enoent branch from 2b418f3 to dfa6409 Compare December 29, 2025 06:06
@ethanndickson ethanndickson added this pull request to the merge queue Dec 29, 2025
Merged via the queue into main with commit ced467a Dec 29, 2025
20 checks passed
@ethanndickson ethanndickson deleted the ethan/fix-subagent-bash-enoent branch December 29, 2025 06:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant