# Race condition silently disables hooks that exit quickly

**URL:** <https://forum.cursor.com/t/race-condition-silently-disables-hooks-that-exit-quickly/165818>\
**Category:** Bug Reports\
**Tags:** auto-run, hooks\
**Created:** [July 15, 2026, 6:15pm UTC](https://forum.cursor.com/t/race-condition-silently-disables-hooks-that-exit-quickly/165818 "2026-07-15T18:15:46Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![ragnoroct](https://sea3.discourse-cdn.com/cursor1/user_avatar/forum.cursor.com/ragnoroct/32/83937_2.png) [@ragnoroct](https://forum.cursor.com/u/ragnoroct)\
**Post date:** [July 15, 2026, 6:15pm UTC](https://forum.cursor.com/t/race-condition-silently-disables-hooks-that-exit-quickly/165818/1 "2026-07-15T18:15:46Z")

</div>

### Where does the bug appear (feature/product)?

Cursor IDE

### Describe the Bug

A race condition causes responses from fast hooks to be ignored. The hook exits successfully, but Cursor receives partial or empty stdout, so permissions  
and input changes are not applied.

### Steps to Reproduce

1. Register a fast Go, Rust, or C `preToolUse` hook for `Shell` that immediately prints `{"permission":"deny","user_message":"blocked"}` and exits 0.
2. Have the Agent issue many separate Shell tool calls concurrently. Do not use one Shell tool call that starts multiple processes.
3. Check the Hooks log.

Some runs report `exit code: 0` with partial or empty output, and the denied command is allowed.

### Expected Behavior

Cursor should capture all output from every hook process and apply each valid response, regardless of execution speed or concurrent hook activity.

### Operating System

Linux

### Version Information

Version: 3.11.19  
VS Code Extension API: 1.125.0  
Commit: bf249e6efb5b097f23d7e21d7283429f0760b740  
Date: 2026-07-12T21:39:24.175Z  
Layout: IDE  
Build Type: Stable  
Release Track: Default  
Electron: 40.10.3  
Chromium: 144.0.7559.236  
Node.js: 24.15.0  
V8: 14.4.258.32-electron.0  
xterm.js: 6.1.0-beta.256  
OS: Linux x64 6.17.0-122035-tuxedo

### Additional Information

A similar issue was confirmed by Cursor in March 2026 and is now closed:

> [@Stop hook followup\_message not captured on Windows – Execution Log shows {} despite valid JSON on stdout](https://forum.cursor.com/t/stop-hook-followup-message-not-captured-on-windows-execution-log-shows-despite-valid-json-on-stdout/155078):
>
> Where does the bug appear (feature/product)? Cursor IDE Describe the Bug On Windows, the stop hook prints valid JSON with followup\_message to stdout and exits with code 0, but the Execution Log shows {} and the agent does not continue with the injected prompt. Steps to Reproduce Configure ~/.cursor/hooks.json: { “version”: 1, “hooks”: { “afterFileEdit”: [{ “command”: “python C:/Users/kyzer/.cursor/hooks/review-implementation-mark-edit.py” }], “stop”: [ { “command”: “python C:/Users/k…

That report may describe the same underlying bug. This still reproduces on Linux in Cursor 3.11.19.

The last good official package I verified was `cursor_1.7.54_amd64.deb` (`1.7.54-1761074318`). The first affected package I verified was `cursor_2.0.4_amd64.deb` (`2.0.4-1761336133`).

In Cursor 3.11.19, the relevant code appears to be in:

`/usr/share/cursor/resources/app/out/vs/workbench/api/node/extensionHostProcess.js`

This path is used by both Desktop and Glass.

Formatted excerpt:

```js
for await (const event of executor.execute(...)) {
  if (event.type === "stdout")
    stdout += event.data.toString("utf8");
  else if (event.type === "stderr")
    stderr += event.data.toString("utf8");
  else if (event.type === "exit")
    return { stdout, stderr, exitCode: event.code ?? 1 };
}

```

I may be missing context, but process exit and pipe delivery are separate events. Cursor appears to process the exit while stdout or stderr events are still pending.

I extracted this control flow into a standalone contrived test. It reproduced the same result: exit code 0 with incomplete stdout. That test only validates the suspected race in the bundled code; the Cursor reproduction is described separately above.

### Does this stop you from using Cursor

Sometimes - I can sometimes use Cursor

---

<div class="post-metadata">

**Author:** ![mohitjain](https://sea3.discourse-cdn.com/cursor1/user_avatar/forum.cursor.com/mohitjain/32/100229_2.png) [@mohitjain](https://forum.cursor.com/u/mohitjain)\
**Post date:** [July 16, 2026, 9:45am UTC](https://forum.cursor.com/t/race-condition-silently-disables-hooks-that-exit-quickly/165818/7 "2026-07-16T09:45:10Z")

</div>

Hey @ragnoroct  
This is a real bug on our side, not your setup.

For fast-exiting command hooks, the process can be treated as finished before all of its stdout has been read, so Cursor ends up with partial or empty output. When that hits a `preToolUse` hook returning `{"permission":"deny"}`, the deny gets dropped and the command runs. Concurrent Shell calls widen the window. I’ve reported this to the team and attached your report.

While a fix is worked on, two things:

1. To shrink the race, have the hook flush stdout and wait a brief moment (around 50ms) before exiting, instead of exiting instantly. It’s not bulletproof, but it gives a fast compiled hook’s output time to be captured.
2. Since this is a timing issue, please don’t rely on a deny hook alone as a hard block for risky commands right now, since a dropped deny means the command can still run. Cursor’s built-in Auto-run command controls are a more reliable layer for hard enforcement until this is fixed.

I’ll update here once a fix ships in a release.

---

<div class="post-metadata">

**Author:** ![Leland\_Hepworth](https://avatars.discourse-cdn.com/v4/letter/l/bbce88/32.png) [@Leland\_Hepworth](https://forum.cursor.com/u/Leland_Hepworth)\
**Post date:** [September 14, 2026, 4:49pm UTC](https://forum.cursor.com/t/race-condition-silently-disables-hooks-that-exit-quickly/165818/8 "2026-09-14T16:49:11Z")

</div>

@mohitjain

Is there any update on this?

The workaround you mentioned does resolve most instances of the issue, but I still occasionally notice it happening. My hook is set up to skip agent commands on an error like this, so risky commands never run, but that means a perfectly good command can randomly get blocked, which degrades agent performance.
