Agent Shell hard-locks: fail-closed beforeShellExecution + MainThreadShellExec not initialized

Where does the bug appear (feature/product)?

Cursor IDE

Describe the Bug

Agent Shell tool calls intermittently fail closed with a Cursor-internal error. The configured beforeShellExecution hook never spawns — Cursor throws before creating the process — and with failClosed: true the Shell tool is blocked. Write/Edit/MCP keep working.

Verbatim error:

Hook "bash \"/Users/johnsolly/code/dotagents/scripts/run-cursor-shell-guards.sh\"" execution failed:
Error: MainThreadShellExec not initialized
Tool blocked because this hook is configured to fail closed (block when it fails).

Evidence this is Cursor-internal, not the hook script

From cursor.hooks.*.log + renderer.log (session 20260708T192232, Cursor 3.10.20; also seen on 3.9.8):

  • The hook never spawns during failures. Failing records show (0ms) exit code: N/A. Outside failure windows the identical script runs clean in <1.1s ((763ms) exit code: 0).
  • Every hook type fails, not just mine: preToolUse, beforeShellExecution, postToolUse, beforeSubmitPrompt, sessionStart, sessionEnd — including the Vercel plugin’s Node hook. A bash script can’t explain that.
  • Failures burst after agent-tab migration. Error bursts start seconds after renderer.log events like:
    [GlassTabPersistenceService] migration_tab_transition.promote_noop {"sourceAgentId":"empty-state-draft",...}
    Successes and failures can interleave in the same window; spawning often recovers minutes later without a reload — consistent with a stale/racing MainThreadShellExec binding for migrated agent tabs.
  • Startup race too: a sessionStart hook failed at 23:22:34.421Z; the same window logged [MainThreadShellExec] $updateShellExecCapabilities 425ms later.

Steps to Reproduce (best effort)

  1. Configure any command hook (fail-closed beforeShellExecution makes impact visible). Example:
{
  "version": 1,
  "hooks": {
    "beforeShellExecution": [
      {
        "type": "command",
        "command": "bash \"/Users/johnsolly/code/dotagents/scripts/run-cursor-shell-guards.sh\"",
        "failClosed": true,
        "timeout": 30
      }
    ]
  }
}
  1. Start an agent in an empty window (no folder), or move a running agent between roots/windows (move_agent_to_root / tab promotion).
  2. Hooks for the migrated agent fail with MainThreadShellExec not initialized; with failClosed: true Shell locks until reload (or until the burst self-recovers).

Expected Behavior

A Cursor-internal failure to spawn the hook should be retried/re-initialized or surfaced as recoverable — not treated as a hook denial that fail-closed blocks Shell for the session.

Related threads searched

Exact match for MainThreadShellExec not initialized: none (only this thread).

Closest cousins — same MainThreadShellExec subsystem, but Session not found / disposed rather than not initialized (sibling lifecycle issue; not claiming identical):

Also checked (different cause / mechanism; titles only because of the new-user 2-link limit): “Peek view not resizable” (console noise with Session not found), Windows hooks launcher failures (hooks intermittently non-functional, Cursor Hooks On Windows, Project-Level Hooks Fail to Execute on Windows), and agent shell stuck via spawn zsh ENOENT / shell-integration hang.

For AI issues: which model did you use?

Grok 4.5 (Cursor agent)

For AI issues: add Request ID with privacy disabled

Data sharing was enabled during occurrences. Conversation/generation IDs from failing hook records (failure window 2026-07-09 00:01–00:18 UTC):

conversation_id generation_id
ded37a3c-a1f4-4548-a194-0102100ed9c8 b44f7969-dd46-4eef-8fc8-65bc4d988d04
6cc232db-66d0-448d-8742-d9c5a7434a3c b2fcd028-280c-42e2-bd24-a58e90ad8874
0cae15f4-7575-48d2-ad94-acb4cb2225bc fb7aab08-4138-45c8-8c9e-b7c4e15f13f3

Several are subagents of one parent session failing simultaneously.

Operating System

MacOS

Version Information

Cursor 3.10.20 (also seen on 3.9.8) · VSCode 1.125.0 · commit 23b9fb205fe595ea2be29da7214e19762d037fc0 · macOS 26.5.1 (Darwin arm64 25.5.0)

Workaround

Developer: Reload Window recovers immediately (bursts also sometimes self-recover within minutes). Keeping failClosed: true intentionally — the guard is the point.

Does this stop you from using Cursor

Yes, I could turn off hooks, but I use them for safety reasons.

Full hook logs available on request.

Hey @jsolly ,

You’ve got the mechanism right. When the shell-exec host hasn’t finished initializing, the internal error is raised before your hook ever spawns, and right now that gets handled like a hook denial - so failClosed: true blocks Shell for the rest of the session. Your core point, that a Cursor-internal init failure shouldn’t fail-closed-block Shell, is exactly the right one, and it’s part of what we’re fixing.

We’ve identified the root cause and a fix for the startup-race trigger is in progress. It isn’t in a downloadable build yet, so Developer: Reload Window stays the right recovery for now (it re-initializes the shell-exec host, which lines up with what you found). And yes - keep failClosed: true, the guard is the point.

One ask: the agent-tab-migration burst you isolated (moving an agent into an empty window) may be a separate variant, and I want to confirm the fix covers it. If you can share the full cursor.hooks.*.log + renderer.log from one of those windows, that’ll let us verify. I’ll update this thread as the fix ships.

Thanks @mohitjain — glad the mechanism matched what you found, and good to hear the startup-race fix is in progress.

Attached are the logs from the agent-tab-migration burst window you asked about:

  • Session 20260708T192232
  • Window window1_wb0 (empty-window workspace)
  • cursor.hooks.workspaceId-empty-window.log — 163× MainThreadShellExec not initialized
  • renderer.log — same window; includes $updateShellExecCapabilities plus several GlassTabPersistenceService migration_tab_transition.promote_noop events (empty-state-draft → agent)

Redacted only user_email values ([REDACTED]). Pre-upload scan found no API keys/tokens/passwords.

cursor-mainthreadshellexec-logs-20260708T192232-wb0.zip (739 KB)

Happy to pull another window if this one isn’t enough to confirm the migration variant.