Windows: Cursor Hooks corrupt Chinese (UTF-8) characters in stdin - replaced with question marks

Where does the bug appear (feature/product)?

Cursor IDE

Describe the Bug

When Cursor invokes hook scripts on Windows, Chinese (and potentially all non-ASCII UTF-8) characters in the JSON data passed via stdin are corrupted and replaced with question marks (? / 0x3F).

Key Finding: The corruption happens before the data reaches the Python script. Analysis of the raw binary data confirms that Chinese characters are already replaced with 0x3f (question mark ASCII) in the stdin stream.

Steps to Reproduce

1、hooks.json
File: ~/.cursor/hooks.json

{
  "version": 1,
  "hooks": {
    "beforeSubmitPrompt": [
      {
        "command": "python .\\hooks\\show_hex.py"
      }
    ],
    "afterAgentResponse": [
      {
        "command": "python .\\hooks\\show_hex.py"
      }
    ]
  }
}

2、show_hex.py
File: ~/.cursor/hooks/show_hex

# hooks/show_hex.py
import sys
import os
from datetime import datetime
from pathlib import Path

def main():
    log_dir = os.path.join(Path.home(), '.cursor')
    hex_file = os.path.join(log_dir, 'raw_hex.txt')
    
    raw_bytes = sys.stdin.buffer.read()
    
    with open(hex_file, 'w', encoding='utf-8') as f:
        f.write(f"原始十六进制转储 - {datetime.now()}\n")
        f.write(f"总字节数: {len(raw_bytes)}\n")
        f.write(f"{'='*80}\n\n")
        
        # 完整十六进制
        f.write("完整十六进制(一行):\n")
        f.write(raw_bytes.hex())
        f.write("\n\n")
        
        # 格式化输出(每行16字节)
        f.write("格式化十六进制:\n")
        for i in range(0, min(len(raw_bytes), 512), 16):
            chunk = raw_bytes[i:i+16]
            hex_str = ' '.join(f'{b:02x}' for b in chunk)
            ascii_str = ''.join(chr(b) if 32 <= b < 127 else '.' for b in chunk)
            f.write(f"{i:08x}  {hex_str:<48}  |{ascii_str}|\n")
        
        f.write("\n\n")
        
        # ASCII 尝试
        f.write("ASCII 解码尝试:\n")
        try:
            ascii_text = raw_bytes.decode('ascii', errors='replace')
            f.write(ascii_text[:1000])
        except Exception as e:
            f.write(f"失败: {e}")
    
    print(f"十六进制已保存到: {hex_file}")
    sys.stdout.buffer.write(b'{"continue": true}')
    return 0

if __name__ == '__main__':
    sys.exit(main())

3、reboot Cursor IDE, input “先取消了 Windows 11 的 xxx” as follows in Chat, you will can see hooks response in Cursor Settings → Hooks:

{
  "conversation_id": "6f91e9cd-76a7-437d-a616-fa9d1fc10354",
  "generation_id": "2715d4a5-e2a2-478f-9521-8d7ea3330ccf",
  "prompt": "明白,I will 告诉你,我还要测试一下",
  "attachments": [
    {
      "type": "file",
      "file_path": "c:\\Users\\Administrator\\.cursor\\hooks.json"
    }
  ],
  "hook_event_name": "beforeSubmitPrompt",
  "cursor_version": "2.0.77",
  "workspace_roots": [
    "/c:/Users/Administrator/.cursor/extensions/specstory.specstory-vscode-0.25.0-universal"
  ]
}

and

{
  "conversation_id": "6f91e9cd-76a7-437d-a616-fa9d1fc10354",
  "generation_id": "2715d4a5-e2a2-478f-9521-8d7ea3330ccf",
  "text": "\n收到,继续测试。需要帮助时告诉我。",
  "hook_event_name": "afterAgentResponse",
  "cursor_version": "2.0.77",
  "workspace_roots": [
    "/c:/Users/Administrator/.cursor/extensions/specstory.specstory-vscode-0.25.0-universal"
  ]
}

you can see this step is ok

4、when hook script was invoked, in log file you will see like this
File: ~/.cursor/raw_hex.txt

原始十六进制转储 - 2025-11-16 18:26:56.775969
总字节数: 318
================================================================================

完整十六进制(一行):
7b22636f6e766572736174696f6e5f6964223a2236663931653963642d373661372d343337642d613631362d666139643166633130333534222c2267656e65726174696f6e5f6964223a2264313437313933352d363933342d343466392d613261662d643432343062626361633039222c2274657874223a225c6e3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f3f222c22686f6f6b5f6576656e745f6e616d65223a2261667465724167656e74526573706f6e7365222c22637572736f725f76657273696f6e223a22322e302e3737222c22776f726b73706163655f726f6f7473223a5b222f633a2f55736572732f41646d696e6973747261746f722f2e637572736f722f657874656e73696f6e732f7370656373746f72792e7370656373746f72792d7673636f64652d302e32352e302d756e6976657273616c225d7d0d0a

格式化十六进制:
00000000  7b 22 63 6f 6e 76 65 72 73 61 74 69 6f 6e 5f 69   |{"conversation_i|
00000010  64 22 3a 22 36 66 39 31 65 39 63 64 2d 37 36 61   |d":"6f91e9cd-76a|
00000020  37 2d 34 33 37 64 2d 61 36 31 36 2d 66 61 39 64   |7-437d-a616-fa9d|
00000030  31 66 63 31 30 33 35 34 22 2c 22 67 65 6e 65 72   |1fc10354","gener|
00000040  61 74 69 6f 6e 5f 69 64 22 3a 22 64 31 34 37 31   |ation_id":"d1471|
00000050  39 33 35 2d 36 39 33 34 2d 34 34 66 39 2d 61 32   |935-6934-44f9-a2|
00000060  61 66 2d 64 34 32 34 30 62 62 63 61 63 30 39 22   |af-d4240bbcac09"|
00000070  2c 22 74 65 78 74 22 3a 22 5c 6e 3f 3f 3f 3f 3f   |,"text":"\n?????|
00000080  3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f 22 2c 22 68   |????????????","h|
00000090  6f 6f 6b 5f 65 76 65 6e 74 5f 6e 61 6d 65 22 3a   |ook_event_name":|
000000a0  22 61 66 74 65 72 41 67 65 6e 74 52 65 73 70 6f   |"afterAgentRespo|
000000b0  6e 73 65 22 2c 22 63 75 72 73 6f 72 5f 76 65 72   |nse","cursor_ver|
000000c0  73 69 6f 6e 22 3a 22 32 2e 30 2e 37 37 22 2c 22   |sion":"2.0.77","|
000000d0  77 6f 72 6b 73 70 61 63 65 5f 72 6f 6f 74 73 22   |workspace_roots"|
000000e0  3a 5b 22 2f 63 3a 2f 55 73 65 72 73 2f 41 64 6d   |:["/c:/Users/Adm|
000000f0  69 6e 69 73 74 72 61 74 6f 72 2f 2e 63 75 72 73   |inistrator/.curs|
00000100  6f 72 2f 65 78 74 65 6e 73 69 6f 6e 73 2f 73 70   |or/extensions/sp|
00000110  65 63 73 74 6f 72 79 2e 73 70 65 63 73 74 6f 72   |ecstory.specstor|
00000120  79 2d 76 73 63 6f 64 65 2d 30 2e 32 35 2e 30 2d   |y-vscode-0.25.0-|
00000130  75 6e 69 76 65 72 73 61 6c 22 5d 7d 0d 0a         |universal"]}..|


ASCII 解码尝试:
{"conversation_id":"6f91e9cd-76a7-437d-a616-fa9d1fc10354","generation_id":"d1471935-6934-44f9-a2af-d4240bbcac09","text":"\n?????????????????","hook_event_name":"afterAgentResponse","cursor_version":"2.0.77","workspace_roots":["/c:/Users/Administrator/.cursor/extensions/specstory.specstory-vscode-0.25.0-universal"]}


Screenshots / Screen Recordings

Operating System

Windows 10/11

Current Cursor Version (Menu → About Cursor → Copy)

Version: 2.0.77 (user setup)
VSCode Version: 1.99.3
Commit: ba90f2f88e4911312761abab9492c42442117cf0
Date: 2025-11-13T23:10:43.113Z
Electron: 37.7.0
Chromium: 138.0.7204.251
Node.js: 22.20.0
V8: 13.8.258.32-electron.0
OS: Windows_NT x64 10.0.26220

For AI issues: which model did you use?

all model

For AI issues: add Request ID with privacy disabled

{
  "conversation_id": "6f91e9cd-76a7-437d-a616-fa9d1fc10354",
  "generation_id": "f07847dc-1173-4492-a796-c3da20d5a00d",
  "prompt": "???I will ???????????",
  "attachments": [],
  "hook_event_name": "beforeSubmitPrompt",
  "cursor_version": "2.0.77",
  "workspace_roots": [
    "/c:/Users/Administrator/.cursor/extensions/specstory.specstory-vscode-0.25.0-universal"
  ]
}
{
  "conversation_id": "6f91e9cd-76a7-437d-a616-fa9d1fc10354",
  "generation_id": "f07847dc-1173-4492-a796-c3da20d5a00d",
  "text": "\n??????????????????",
  "hook_event_name": "afterAgentResponse",
  "cursor_version": "2.0.77",
  "workspace_roots": [
    "/c:/Users/Administrator/.cursor/extensions/specstory.specstory-vscode-0.25.0-universal"
  ]
}

Additional Information

In the above description, the values ​​corresponding to conversation_id and generation_id may not match. However, when the scripts for the beforeSubmitPrompt and afterAgentResponse hooks are called by Cursor, the data (prompt or text) they receive will be garbled if they contain Chinese characters.

Does this stop you from using Cursor

No - Cursor works, but with this issue

Hey, thanks for the report.

From your screenshot, the Chinese characters are already corrupted directly in the Hooks UI inside Cursor, which means the problem occurs inside Cursor before the data even reaches your Python script.

This is clearly a Windows‑specific encoding bug: Cursor isn’t handling UTF‑8 correctly when running hooks. I’ll pass this on to the team.

A couple of questions to help with the investigation:

  • What is your Windows system locale? (Control Panel > Region > Administrative tab > “Language for non‑Unicode programs”)
  • Is the “Beta: Use Unicode UTF‑8 for worldwide language support” option enabled in that same window?

Please let me know what your locale settings are.

Thank you for your reply. This is my current regional setting.

Looking forward to your reply ~

Thanks for providing the locale information!

There’s a possible temporary workaround: enable the “Beta: Use Unicode UTF-8 for worldwide language support” checkbox in your Windows Regional Settings (as shown in your second screenshot), then restart Cursor. This will make Windows use UTF-8 as the system encoding and may prevent the text corruption.

However, this is clearly a bug in Cursor’s hook implementation on Windows, the app should handle UTF-8 correctly regardless of the system locale settings. I’ve already escalated this issue to the engineering team. Your detailed bug report with hex dumps and locale info will help them fix it properly.

Please let me know if enabling the UTF-8 beta mode helps as a temporary workaround.

I have setted checkbox in my Windows Regional Settings, restart Cursor, submit prompt “test 一下 hook 脚本,不需要你推理,直接回复即可”, in Cursor IDE Hook Setting “Execution Log” Chinese characters response is ok, but in log file cursor isn’t handling UTF‑8 correctly when running hooks.

{
  "conversation_id": "66069daa-c7b9-4b39-9aef-af65f40e7dd9",
  "generation_id": "050ff528-d32a-4699-b7d4-6fbff237a691",
  "text": "\n**?????**\n\n1. ? Node.js ?????v25.2.0\n2. ? npm ???11.6.2\n3. ? package.json ????? test ??\n4. ?? ???????????test-*.mjs???????? hook ??\n\n**?????**\n- ???????????? hook ??\n- `.git/hooks` ?????????.sample?\n- ?????? hook ????\n\n????\n1. ???????? hook ???\n2. ????????? hook ?????\n3. ????????????????",
  "hook_event_name": "afterAgentResponse",
  "cursor_version": "2.0.77",
  "workspace_roots": [
    "/g:/WORKSPACE/cursor-space/vscode-internal-command-mcp-server"
  ]
}

This topic was automatically closed 22 days after the last reply. New replies are no longer allowed.