You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Error: inspector: source state exceeds the source-frame byte limit
at InspectorSourceBuffer.setState (…/lib/index.js:996:10)
at HostBridgePublisher.setState (…/lib/index.js:1109:16)
at HostInspectorSource.setState (…/lib/index.js:836:18)
exit=1
同一环境下扫边界:126,915 接受,126,916 拒绝,死区 61 字节,与 B 一致。平台从 macOS 换成 Linux、代码从源码换成发布产物,结果不变。
Current behavior
两天内崩溃四次,栈完全一致:
dsh: fatal uncaught exception: Error: inspector: source state exceeds the source-frame byte limit
at InspectorSourceBuffer.setState (…/dsh-experimental-inspector/lib/index.js:996:10)
at HostBridgePublisher.setState (…/dsh-experimental-inspector/lib/index.js:1109:16)
at HostInspectorSource.setState (…/dsh-experimental-inspector/lib/index.js:836:18)
at … (…/dsh-experimental-inspector/lib/index.js:2322:13)
at publish (…/dsh-experimental-inspector/lib/index.js:2294:3)
at process.processTicksAndRejections (node:internal/process/task_queues:104:5)
setState 在抛出前已把 state 回滚(buffer.ts:64-68),所以不是状态损坏,纯粹是一个没人接的异常。
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
Summary
@deepseek-ai/dsh-experimental-inspector通过publishCordisTree把 Cordis 树快照作为cordis/treestate 发布。collector 与 buffer 用同一个 128 KB 帧上限校验,但量的是不同对象:collector 量裸快照,buffer 量包装后的 record{monotonicMs, topic, payload}。两者相差约 61 字节,形成一段 collector 放行、buffer 必拒的区间。该拒绝发生在
queueMicrotask内,调用链上没有 try/catch,最终以dsh: fatal uncaught exception结束整个 host 进程。桌面端表现为整程序退出,用户丢失当前会话。影响范围是 Cordis 树接近 128 KB 的 profile:插件装载、MCP 上下线、会话切换都会触发发布,也就都可能触发退出。
Reproduction
A. 现场复现(0.2.1-rc.2 桌面版)
@deepseek-ai/dsh-experimental-inspector-profile,另挂若干第三方 bundle,inspector 使用默认配置。ctx.plugin({ name, apply() {} })挂空插件,每 20 ms 25 个。crash-*-host.log出现本文的栈。654 个 fiber 时距上限只差约 150 个节点(约 19 KB),说明该 profile 一直贴着上限。
B. 最小单元复现(确定性)
collector 的接受上限是
maxSourceFrameBytes - 4096 = 126,976:实测边界:126,976 被拒,126,915 通过,死区 61 字节。把时间戳换成 16 位再测,边界挪到 126,909,死区 67 字节——宽度随
monotonicMs位数变化,不是常量。C. 独立验证(Linux 容器,npm 发布产物)
node:24-bookworm容器内npm i @deepseek-ai/dsh-experimental-inspector@0.2.1-rc.2,用startInspector()返回的真实 source 调setState('cordis/tree', <126,976 字节的 payload>):同一环境下扫边界:126,915 接受,126,916 拒绝,死区 61 字节,与 B 一致。平台从 macOS 换成 Linux、代码从源码换成发布产物,结果不变。
Current behavior
两天内崩溃四次,栈完全一致:
setState在抛出前已把 state 回滚(buffer.ts:64-68),所以不是状态损坏,纯粹是一个没人接的异常。Expected behavior
单帧观测超限应当被丢弃并记录,下一次
internal/plugin或internal/status事件重试。inspector 的观测失败不应该终结 host 进程。根因
collector 建出来时预留了 4096 字节帧开销(
host/plugin.ts:80-83):collector 据此裁剪,保证返回的裸快照满足
jsonByteLength(snapshot) <= maxBytes(collector.ts:104-110)。但 buffer 校验的是状态的 JSON 编码(
buffer.ts:157-160),而 state 里存的是record()构造的{monotonicMs, topic, payload}(buffer.ts:134-146):于是快照要同时满足两个宽度不同的条件:
信封固定为
49 + String(monotonicMs).length字节,这就是死区的来源。另有一处同样致命但本次未触发:
collector.ts:111的Cordis root exceeds the source-frame byte limit从同一个微任务抛出,只修 buffer 不足以覆盖。版本比对:
0.1.7-rc.2、0.2.0-rc.2、0.2.1-rc.2、0.2.1-rc.5、0.2.2-alpha.2的上述代码一致,不是回归,升级到目前最新版也不能解决。Environment
0.2.1-rc.2,Electron44.7.0,Node24.21.0,macOS arm64@deepseek-ai/dsh-experimental-inspector0.2.1-rc.2@deepseek-ai/dsh-experimental-inspector-profile及若干第三方 bundlemaxSourceFrameBytes或maxCordisNodesAll reactions