E2E: use undici 6, the major Node 22's fetch bundles, for the shared dispatcher
undici 7's Agent under Node 22's fetch failed request bodies ("fetch failed" on the
legacy cache and artifact uploads, "invalid content-length header" from Octokit). The
module now refuses to load with a clear message if the majors ever differ.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01M5tHXfgBQaLEPM9iUPrp8n- CI / Typecheck and bundlesuccess
- CI / Unit tests (1/2)success
- CI / Unit tests (2/2)success
- End-to-end / End-to-end (agent reviews, tasks, Today)success
- End-to-end / End-to-end (git, PRs, Actions)success
- End-to-end / End-to-end (large pushes)success
- End-to-end / End-to-end (passkeys, registry, email)success
- End-to-end / End-to-end (real histories)success
- End-to-end / End-to-end (runner Docker)success
- End-to-end / End-to-end (security)success
3 files changed+18−3
modifiedapps/diffinery/package.json+1−1View file
| @@ -46,7 +46,7 @@ | ||
| 46 | 46 | "react": "19.2.0", |
| 47 | 47 | "react-dom": "19.2.0", |
| 48 | 48 | "typescript": "^5.9.3", |
| 49 | - "undici": "7.29.1", | |
| 49 | + "undici": "6.23.0", | |
| 50 | 50 | "vitest": "^4.1.0", |
| 51 | 51 | "wrangler": "^4.149.0" |
| 52 | 52 | } |
modifiedapps/diffinery/test/e2e/fresh-connections.mjs+9−0View file
| @@ -5,6 +5,15 @@ | ||
| 5 | 5 | // waits unread, the next fetch reuses the dead connection and fails with "fetch failed" (other side |
| 6 | 6 | // closed, UND_ERR_SOCKET), and so does the test. A new localhost connection per request costs well under |
| 7 | 7 | // a millisecond; Node's fetch and WebSocket use this dispatcher. |
| 8 | +// | |
| 9 | +// Node's fetch is its own bundled undici, which only works with a dispatcher from the same major | |
| 10 | +// version (undici 7's Agent under Node 22's fetch fails request bodies), so the undici dev dependency | |
| 11 | +// follows Node's: Node 22 bundles undici 6. | |
| 8 | 12 | import { Agent, setGlobalDispatcher } from "undici"; |
| 13 | +import { createRequire } from "node:module"; | |
| 9 | 14 | |
| 15 | +const ours = createRequire(import.meta.url)("undici/package.json").version; | |
| 16 | +if (ours.split(".")[0] !== process.versions.undici.split(".")[0]) { | |
| 17 | + throw new Error(`apps/diffinery's undici dev dependency (${ours}) must have the major version of the undici in Node ${process.version} (${process.versions.undici})`); | |
| 18 | +} | |
| 10 | 19 | setGlobalDispatcher(new Agent({ pipelining: 0 })); |
modifiedpnpm-lock.yaml+8−2View file
| @@ -122,8 +122,8 @@ | ||
| 122 | 122 | specifier: ^5.9.3 |
| 123 | 123 | version: 5.9.3 |
| 124 | 124 | undici: |
| 125 | - specifier: 7.29.1 | |
| 126 | - version: 7.29.1 | |
| 125 | + specifier: 6.23.0 | |
| 126 | + version: 6.23.0 | |
| 127 | 127 | vitest: |
| 128 | 128 | specifier: ^4.1.0 |
| 129 | 129 | version: 4.1.11(@types/node@22.20.5)(vite@8.3.4(@types/node@22.20.5)(esbuild@0.25.11)(yaml@2.9.1)) |
| @@ -2187,6 +2187,10 @@ | ||
| 2187 | 2187 | undici-types@6.21.0: |
| 2188 | 2188 | resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} |
| 2189 | 2189 | |
| 2190 | + undici@6.23.0: | |
| 2191 | + resolution: {integrity: sha512-VfQPToRA5FZs/qJxLIinmU59u0r7LXqoJkCzinq3ckNJp3vKEh7jTWN589YQ5+aoAC/TGRLyJLCPKcLQbM8r9g==} | |
| 2192 | + engines: {node: '>=18.17'} | |
| 2193 | + | |
| 2190 | 2194 | undici@7.29.0: |
| 2191 | 2195 | resolution: {integrity: sha512-IDxfleLmmbSskfWSUATiN1nfn2rDuvnMOqb5CWR92iIfojA0Ud+ulOAAEQ57LPr9rWmsreUyf5lwyao+7GNNVw==} |
| 2192 | 2196 | engines: {node: '>=20.18.1'} |
| @@ -4094,6 +4098,8 @@ | ||
| 4094 | 4098 | |
| 4095 | 4099 | undici-types@6.21.0: {} |
| 4096 | 4100 | |
| 4101 | + undici@6.23.0: {} | |
| 4102 | + | |
| 4097 | 4103 | undici@7.29.0: {} |
| 4098 | 4104 | |
| 4099 | 4105 | undici@7.29.1: {} |