Repository navigation
[macOS] Uncaught main-process exception: setTypeOfService EINVAL (internal undici unguarded) #9557
Replies: 2 comments
|
Confirmed root cause, plus a one-line fix on the DSH side. Verified on macOS 26 (Tahoe), DSH 1. Why the exception escapes
if (socket.setTypeOfService) {
socket.setTypeOfService(request.typeOfService); // no try/catch
}
if (tos !== this[kSetTOS]) {
this[kSetTOS] = tos; // set *before* the syscall
const err = this._handle.setTypeOfService(tos);
if (err && !isWindows) {
throw new ErrnoException(err, 'setTypeOfService'); // :913
}
}
} else {
// Unsupported socket family (e.g. AF_UNIX)
args.GetReturnValue().Set(UV_EINVAL);
return;
}(It picks Upstream undici already guards this (nodejs/undici#5547), but it landed in Node 26. There is no backport to the Node 24 line, which is what Electron 44 ships. 2. Reachability inside DSH: only two call sites, both in the main process
Line 12194 already does the right thing, so this looks like an oversight on Reachability per launch is 3. Full stack (from the modal dialog)Note 4. It is worse than a log line: it is modalThere is no 5. Suggested fixCheapest first:
6. Already ruled out (so this doesn't get re-investigated)
Happy to run any instrumented build if it helps pin down which socket ends up in the |
|
补一个 2.0.21-next 仍然复现的数据点,并补充一个之前没记录过的次生故障:崩溃之后应用无法靠重启自愈。 环境与现场
新增:崩溃后的 60 秒启动死锁第一次崩溃后旧 host 子进程没有退出(
也就是说,用户遇到这个崩溃之后,反复重开应用是没用的,反而会不断 spawn 出起不来的 host;只能等残留进程被清掉,或者手动强制退出再试。这比单次崩溃本身的伤害更大。 与已有定位的关系根因与 #9557 的结论一致,不需要重新排查:主进程 建议(在 #9557 的三条之外补一条恢复逻辑)
诊断材料这次的三组诊断都在:崩溃弹窗截图、 另外 #11309 是同一崩溃在 0.2.1-rc.1 上的报告,可以一起看。 |
Uh oh!
There was an error while loading. Please reload this page.
==================================================================
[macOS] 主进程未捕获异常 setTypeOfService EINVAL
Uncaught main-process exception: setTypeOfService EINVAL
(内置 undici 裸调用 + Node 仅在 Windows 做了容错)
(internal undici calls it unguarded; Node only swallows the error on Windows)
【环境 / Environment】
中:App 为 DeepSeek Harness 桌面版 0.2.0-rc.2(nightly,2026-09-29 构建,
已是更新源当前最新版);系统 macOS(Apple Silicon);系统代理已关闭,
无 VPN、无网络扩展;重启 Mac 后问题依旧。
EN: DeepSeek Harness desktop 0.2.0-rc.2 (nightly, built 2026-09-29, latest on
the update feed); macOS on Apple Silicon; system proxy disabled, no VPN and
no network extension installed. The error persists even after a full reboot.
【现象 / Symptom】
中:使用中偶发弹窗 "A JavaScript error occurred in the main process",
非致命,点 OK 后可继续使用,但反复出现。
EN: A dialog "A JavaScript error occurred in the main process" pops up
intermittently during normal use. It is non-fatal — the app keeps working
after clicking OK — but it recurs constantly.
【错误栈 / Stack trace(原文)】
Uncaught Exception:
Error: setTypeOfService EINVAL
at Socket.setTypeOfService (node:net:684:13)
at writeH1 (node:internal/deps/undici/undici:8022:16)
at Object.write (node:internal/deps/undici/undici:7758:18)
at _resume (node:internal/deps/undici/undici:9656:54)
at resume (node:internal/deps/undici/undici:9589:7)
at Client. (node:internal/deps/undici/undici:9370:35)
at node:internal/deps/undici/undici:9539:26
at Socket. (node:internal/deps/undici/undici:3342:13)
【定位 / Root cause(已逐项核对安装包内文件 / verified against the installed bundle)】
中:1) 崩溃走的是 Node 运行时内置的 node:internal/deps/undici(运行时二进制
Contents/Resources/runtime/primary-runtime/dependencies/node/bin/node 实际版本
为 v24.21.0)。该内置 undici 写请求时是裸调用,没有任何保护:
EN: 1) The crash goes through the undici bundled INSIDE the Node runtime
(node:internal/deps/undici; the bundled binary reports v24.21.0). That
internal undici calls the API unguarded when writing a request:
中:2) Node 的 net.Socket.setTypeOfService 原生实现只对 Windows 做了
best-effort 容错,macOS 上直接抛出:
EN: 2) Node's net.Socket.setTypeOfService implementation treats the call as
best-effort on Windows only, and rethrows on macOS:
中: 当 socket 处于瞬时状态(睡眠唤醒、网络切换、连接复用等)时,内核对
IP_TOS 返回 EINVAL,异常无人捕获,一路冒泡到主进程弹出对话框。
EN: When the socket is in a transient state (after sleep/wake, a network
switch, connection reuse, etc.), the kernel returns EINVAL for IP_TOS; the
exception is uncaught and bubbles all the way up to the main process, which
shows the dialog.
中:3) 关键反差:app.asar 内打包的较新 undici 已经修复了这个问题——
setTypeOfService 助手外面包了 try/catch,注释写明 "QoS marking is
best-effort. setTypeOfService() can throw synchronously on some platforms
depending on socket state, but that must not abort the request."
但主进程内置 fetch 走的仍是上面那份旧的内置 undici,没有用上修复。
EN: 3) Key contrast: the NEWER undici bundled in app.asar already fixes this —
its setTypeOfService helper is wrapped in try/catch with the comment
"QoS marking is best-effort ... must not abort the request". But the
main-process built-in fetch still uses the older internal undici, so the fix
is never reached on this path.
【复现 / Reproduction】
中:在普通 IPv4、IPv6、IPv4-mapped socket 上设置 ToS 0~255 全部正常,无法稳定
复现;只在特定 socket 状态下偶发,与新版 undici 注释中 "throws synchronously
on some platforms depending on socket state" 的描述一致。
EN: Setting ToS 0–255 works fine on ordinary IPv4, IPv6, and IPv4-mapped sockets,
so it cannot be reproduced deterministically; it only fires under specific
socket states, consistent with the note "throws synchronously on some
platforms depending on socket state".
【建议修复 / Suggested fix】
中:三选一即可:
a. 升级内置 Electron/Node 到包含 undici best-effort 修复的版本;
b. 让主进程 HTTP 请求统一走 app.asar 中已带 try/catch 的那份 undici;
c. 在 Node 的 setTypeOfService 中对 macOS 也应用与 Windows 相同的
best-effort 容错(EINVAL 时不抛出)。
EN: Any of the following would fix it:
a. Upgrade the bundled Electron/Node to a version whose internal undici
includes the best-effort fix;
b. Route main-process HTTP requests through the undici already shipped in
app.asar (which has the try/catch);
c. Apply the same best-effort handling to macOS as Windows in
Socket.setTypeOfService (do not throw on EINVAL).
【影响 / Impact】
中:非致命但高频干扰,且用户无法通过关闭代理、重启、清理网络接口规避;
ToS 仅为 QoS 标记,忽略其错误对请求功能无影响。
EN: Non-fatal but high-frequency and unavoidable via proxy settings, reboot, or
network-interface cleanup. ToS is only a QoS hint, so ignoring its error has
no functional impact on the request.
All reactions