Skip to content

fix(host): guard the bundled undici write path against setTypeOfService EINVAL - #824

Open
eatmoreduck wants to merge 1 commit into
dataelement:mainfrom
eatmoreduck:fix/821-type-of-service-guard
Open

eatmoreduck wants to merge 1 commit into
dataelement:mainfrom
eatmoreduck:fix/821-type-of-service-guard

Conversation

@eatmoreduck

Copy link
Copy Markdown
Contributor

Motivation

Fixes #821.

Node 24's bundled undici (7.29.x) calls socket.setTypeOfService on every HTTP/1.1 request write with no try/catch. When a connection is reset in the window between connect and the first write, macOS setsockopt(IP_TOS) answers EINVAL, the synchronous throw escapes as an uncaught exception, and the Harness host dies — the reporter's crash logs show exactly this stack, and entering the plugin market fires enough requests to hit the reset window. Upstream fixed it by ignoring type-of-service errors (undici#5547, 7.x backport undici#6076), but the backport merged 2026-10-27 and no Node 24 release ships it yet, so the bundled Node 24.21.0 runtime cannot avoid it by configuration.

Description

  • New build/type-of-service-guard.mjs: wraps Socket.prototype.setTypeOfService, swallows exactly EINVAL with a one-time [harness-node] diagnostic, rethrows everything else. Installs only when the runtime reports process.versions.undici older than 7.30.1, so the guard self-disables with the runtime bump and needs no removal PR.
  • build/harness-node-entry.mjs installs the guard before the DSH entry loads — same reach as the existing windowsHide enforcement in that file: every fetch in the host process tree (Harness internals, dshmarket, plugins) is covered without an upstream fix in each caller.
  • Four contract tests in test/harness-node-entry.test.ts: EINVAL swallowed + warned once, non-EINVAL rethrown, no install on undici ≥ 7.30.1 (or 8.x), no install when the runtime lacks the API (Node ≤ 22 — also verifies the real node:net prototype is untouched on this dev runner).

Type-of-service 0 is semantically a no-op, and the upstream fix ignores TOS errors entirely, so swallowing EINVAL loses nothing on the wire.

Validation

  • npx vitest run test/harness-node-entry.test.ts: 34/34 pass.
  • Full suite npx vitest run test/: 2,696 passed / 39 failed — the 39 failures are the pre-existing office/ppt/docx .mjs set that fails identically on a clean main checkout in this environment (dev install ran with --ignore-scripts; npx patch-package applied before the run).
  • npm run typecheck: clean.

The platform-level EINVAL cannot be reproduced on this dev machine (its Node 22 predates setTypeOfService); the wrapper behavior is pinned by the contract tests, and the crash stack in #821 plus upstream undici#5544 carry the platform evidence.

AI Disclosure

Made by an AI coding agent (GLM coding agent, Zhipu), human-supervised.

…ce EINVAL

Node 24's bundled undici (7.29.x) calls socket.setTypeOfService on every
HTTP/1.1 request write with no try/catch. A connection reset in the
window between connect and the first write makes macOS setsockopt(IP_TOS)
answer EINVAL, the synchronous throw escapes as an uncaught exception,
and the Harness host dies — entering the plugin market fires enough
requests to hit it (dataelement#821). Upstream fixed by ignoring type-of-service
errors (undici#5547, 7.x backport undici#6076), but no Node 24 release
ships the backport yet.

The harness node entry now wraps Socket.prototype.setTypeOfService before
the DSH entry loads — same reach as the windowsHide enforcement in that
file: every fetch in the process tree is covered without an upstream fix
in each caller. EINVAL is swallowed with a one-time diagnostic; other
errors still surface. The guard self-disables once the bundled runtime
reports undici >= 7.30.1, so it disappears with the runtime bump.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] 进入插件市场时 host 进程崩溃:setTypeOfService EINVAL(内置 Node 24.21.0 / undici 7.29.1 上游 bug)

1 participant