[Bug] 会话含孤立代理项(emoji 被文本截断劈半)后永久卡死:UnicodeEncodeError 'utf-8' codec can't encode character '\ud83d' surrogates not allowed → 500
Nobody has claimed this yet.
- Dominant language
- No language data
- Stars
- 22
- Forks
- 1
- PR merge metrics
- No merged PRs in 30d
Description
环境
- ZCode 桌面版 3.10.1 (3.10.1.6272),macOS arm64 (darwin 25.5.0)
- 模型渠道:Z.ai (GLM)
问题摘要
使用 computer-use 的 get_app_state 读取 Notion 桌面端窗口的无障碍树后,会话永久卡死:之后发送的任何消息都返回 500、无任何回复,无法从界面恢复;重开会话/重发消息均复发。同一天内 3 个会话以完全相同的方式卡死。
报错原文:
[500]['utf-8' codec can't encode character '\ud83d' in position 34504: surrogates not allowed][20260830220348c8865dc95cfd42e9]
根因(已通过本地会话库扫描验证)
get_app_state返回 AX 树时,超长元素文本用…截断;截断点落在某个 emoji 的 UTF-16 代理对中间,留下孤立高位代理\ud83d(工具结果原文出现...\n\n\ud83d…)。- 该工具结果被原样存入会话数据库(作为
\ud83dJSON 转义序列)。 - 此后每次发消息:装载会话历史 → Python
json.loads→str.encode('utf-8')抛UnicodeEncodeError: surrogates not allowed→ 500 → 本轮无输出。重试永远命中同一坏字符,表现为会话"卡死"。 - 扫描本地全部 19,763 行 message/part:中毒行恰好 3 行(3 个会话各 1 行),全部是
get_app_state工具结果,各含 2 个坏字符串。三个会话读的是同一页面状态,在完全相同的位置中招——截断点是确定性的。
复现步骤
- macOS 打开 Notion 桌面端,进入含大量 emoji 图标(侧边栏页面图标等)的页面;
- 用 computer-use
get_app_state读取该窗口(该页面返回 1000 元素、长文本被截断); - 之后发送任意消息 → 500,会话永久卡死。
期望行为
- AX 文本截断按码点而非 UTF-16 码元切分,不产生孤立代理项;
- 客户端在序列化/装载会话历史时对孤立代理项做防御性清洗(替换为 U+FFFD),单个中毒的工具结果不应导致整个会话永久不可用。
实际行为
每次请求 500,会话无响应,用户只能弃用会话。
本地临时修复(已验证有效)
将 3 个中毒 part 行中的 \ud83d… 替换为 … 后,3 个会话全部恢复正常,说明存储层无其他问题。
相关
#61 是同族问题(Unicode LINE SEPARATOR 导致 transport 崩溃),建议一并考虑统一的异常字符清洗层。
TraceID: 20260830220348c8865dc95cfd42e9
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reproducing the macOS Notion case through the computer-use get_app_state flow, then trace where its truncated AX text is serialized into the session database and loaded into message history. Done means truncation no longer leaves an isolated surrogate, and existing poisoned tool results are defensively cleaned so later messages do not return 500.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- macos, python
- Domain
- desktop
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100