# \[HOOKS\] Hook 1 failed with exit code 1 undefined

**URL:** <https://forum.cursor.com/t/hooks-hook-1-failed-with-exit-code-1-undefined/160992>\
**Category:** Bug Reports\
**Tags:** windows, hooks\
**Created:** [May 19, 2026, 9:19am UTC](https://forum.cursor.com/t/hooks-hook-1-failed-with-exit-code-1-undefined/160992 "2026-05-19T09:19:30Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![Tate\_Foster](https://avatars.discourse-cdn.com/v4/letter/t/ed8c4c/32.png) [@Tate\_Foster](https://forum.cursor.com/u/Tate_Foster)\
**Post date:** [May 19, 2026, 9:19am UTC](https://forum.cursor.com/t/hooks-hook-1-failed-with-exit-code-1-undefined/160992/1 "2026-05-19T09:19:30Z")

</div>

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

Cursor IDE

### Describe the Bug

[HOOKS] Hook 1 failed with exit code 1 undefined  
I’m trying to set up Cursor hooks on my Windows computer, but I keep getting the error above regardless of whether I use Node or PowerShell commands.

### Steps to Reproduce

{  
“version”: 1,  
“hooks”: {  
“beforeSubmitPrompt”: [  
{  
“command”: “node C:/Users/yi.chen/.cursor/hooks/works-cursor-task-track-start.js”,  
“timeout”: 5  
}  
],  
“stop”: [  
{  
“command”: “node C:/Users/yi.chen/.cursor/hooks/works-cursor-task-track-end.js”,  
“timeout”: 5  
},  
{  
“command”: “node C:/Users/yi.chen/.cursor/hooks/works-cursor-task-track-usage.js”,  
“timeout”: 5  
}  
]  
}  
}

{  
“version”: 1,  
“hooks”: {  
“beforeSubmitPrompt”: [  
{  
“command”: “powershell -NoProfile -NonInteractive -ExecutionPolicy Bypass -File "C:/Users/yi.chen/.cursor/hooks/works-cursor-task-track-start.ps1"”,  
“timeout”: 5  
}  
],  
“stop”: [  
{  
“command”: “powershell -NoProfile -NonInteractive -ExecutionPolicy Bypass -File "C:/Users/yi.chen/.cursor/hooks/works-cursor-task-track-end.ps1"”,  
“timeout”: 5  
},  
{  
“command”: “powershell -NoProfile -NonInteractive -ExecutionPolicy Bypass -File "C:/Users/yi.chen/.cursor/hooks/works-cursor-task-track-usage.ps1"”,  
“timeout”: 5  
}  
]  
}  
}

### Operating System

Windows 10/11

### Version Information

IDE 3.3.30

### Does this stop you from using Cursor

Yes - Cursor is unusable

---

<div class="post-metadata">

**Author:** ![deanrie](https://sea3.discourse-cdn.com/cursor1/user_avatar/forum.cursor.com/deanrie/32/1263_2.png) [@deanrie](https://forum.cursor.com/u/deanrie)\
**Post date:** [May 19, 2026, 11:51am UTC](https://forum.cursor.com/t/hooks-hook-1-failed-with-exit-code-1-undefined/160992/5 "2026-05-19T11:51:02Z")

</div>

Hey, let’s break it down. `exit code 1` means the script itself crashed. The hooks infrastructure ran fine and just reported the exit code. The `undefined` at the end is just log noise and doesn’t affect debugging.

Hook names

`beforeSubmitPrompt` and `stop` in your config are both valid, active events. Alongside the classic `before*` and `after*`, Cursor also added newer names: `preToolUse`, `postToolUse`, `subagentStart`, `subagentStop`, `preCompact`, `sessionStart`, `sessionEnd`, and `workspaceOpen` (App lifecycle) [Hooks | Cursor Docs](https://cursor.com/docs/hooks). These are additions, not renames. `beforeSubmitPrompt` is still supported. If you saw `UserPromptSubmit` or `PreToolUse` in PascalCase, that’s Claude Code’s API, not Cursor, and it’s easy to mix them up.

Also worth knowing about known issues with `beforeSubmitPrompt` in recent versions: `updated_input` gets silently dropped [Bug: `beforeSubmitPrompt` hook `updated_input` is silently stripped — modified prompt never reaches the model](https://forum.cursor.com/t/bug-beforesubmitprompt-hook-updated-input-is-silently-stripped-modified-prompt-never-reaches-the-model/158883), and `block` sometimes doesn’t block [beforeSubmitPrompt hook block is broken](https://forum.cursor.com/t/beforesubmitprompt-hook-block-is-broken/156823). This isn’t directly related to your exit 1, but it’s good context. If your script’s goal is to “tell” something to the agent, the most reliable approach right now is using `stop` plus `followup_message`.

Where to see the script stderr

1. `View` \> `Output` \> `Hooks`  
This shows stderr with the real reason for exit 1.
2. Cursor Settings \> Hooks \> Execution Log  
Handy, but it’s limited to 100 entries.
3. Full log without trimming  
`Command Palette` \> `Developer: Open Logs Folder`, then check `cursor.hooks.log` for the current session.

Most common exit 1 causes on Windows

1. UTF-8 in stdin  
Confirmed Windows bug: the payload can arrive without proper UTF-8. Non ASCII characters turn into `?`, multibyte chars can get cut, then `JSON.parse(stdin)` throws `SyntaxError`. If your prompts can include Cyrillic or emoji, this is the top suspect. Related threads:  
[[Windows] Hooks receive corrupted UTF-8 (? instead of Cyrillic)](https://forum.cursor.com/t/windows-hooks-receive-corrupted-utf-8-instead-of-cyrillic/150363)  
[Hook stdin pipe double-encodes non-ASCII on non-UTF-8 Windows](https://forum.cursor.com/t/hook-stdin-pipe-double-encodes-non-ascii-on-non-utf-8-windows/159259)  
In Node, explicitly do `process.stdin.setEncoding('utf8')` before reading. System workaround: `Control Panel` \> `Region` \> `Administrative` \> `Beta: Use Unicode UTF-8 for worldwide language support`, then restart Cursor. It doesn’t always help.
2. Accessing a missing payload field  
If the code does something like `payload.text.includes(...)` or `payload.message...` without a guard, you’ll get a `TypeError` and exit 1.
3. `workspace_roots` on Windows  
Paths can come in a weird format like `"/d:/code/code/"` with a leading slash and a lowercase drive letter. A direct `fs.existsSync(payload.workspace_roots[0])` can fail unless you normalize.
4. Unstable hook `cwd`  
The hook process working directory isn’t always the workspace root and it has changed between releases:  
[Inconsistent working directory for plugin hook commands](https://forum.cursor.com/t/inconsistent-working-directory-for-plugin-hook-commands/153236)  
[Stop hook uses wrong (or different) working directory when executing](https://forum.cursor.com/t/stop-hook-uses-wrong-or-different-working-directory-when-executing/157195)  
Relative paths like `require('./helpers')` or `fs.readFileSync('./config.json')` can break. Use `__dirname` for files next to the script and a normalized `workspace_roots[0]` for project paths.

Response contract

JSON in stdin, JSON out to stdout. Not stderr. No BOM. No prefix `console.log` before the JSON. Response fields are snake\_case like `user_message`, `followup_message`, not camelCase. By event:

- `beforeSubmitPrompt`: `{"continue": true|false, "user_message": "..."}` or just `{}`
- `stop`: `{"followup_message": "..."}` optional, or `{}`

At the end, use `process.stdout.write(...)` and an explicit `process.exit(0)` after flush.

On Windows there’s another known issue where valid JSON can show up as `{}` in the Execution Log: [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)  
It doesn’t cause exit 1, but keep it in mind.

About the PowerShell variant

`-File` has limited support with stdin piping. The most reliable setup is calling `node.exe` directly from `hooks.json` like your first variant. If you still need PowerShell, read stdin explicitly:

```powershell
$payload = [Console]::In.ReadToEnd() | ConvertFrom-Json

```

Manual check to rule out Cursor

```powershell
$payload = '{"hook_event_name":"beforeSubmitPrompt","prompt":"test","conversation_id":"x","generation_id":"y","workspace_roots":["/c:/Users/yi.chen/"]}'
$payload | node C:/Users/yi.chen/.cursor/hooks/works-cursor-task-track-start.js

```

If it fails, the issue is in the script. If it works cleanly but fails inside Cursor, it’s likely `PATH` or `cwd` or payload parsing, see the UTF-8 point above.

Duplicate hooks

Cursor loads three `hooks.json` levels in parallel:

- project local: `<workspace>/.cursor/hooks.json`
- user global: `C:\Users\<user>\.cursor\hooks.json`
- enterprise or system: `C:\ProgramData\Cursor\hooks.json`

If the same script is registered in multiple places, you’ll see multiple runs for one event. Check for old or duplicated configs.

What to share for an exact diagnosis

- All three `hooks.json` files (project, user, ProgramData if present)
- The full section from `View` \> `Output` \> `Hooks` from the moment you start the agent
- Your `works-cursor-task-track-start.js`
- Cursor version `Help` \> `About` and `node -v` (Node 18 vs 20+ can behave differently with `process.stdin`)
