CodeSampleX

Sample

undici 7.29.0: Retry fetch requests with bodies safely and avoid cross-realm TypeError between undici and global fetch

Verified sample for npm undici 7.29.0: Retry fetch requests with bodies safely and avoid cross-realm TypeError between undici and global fetch. The contract…

sha256:58c13cc15f12e5f7e9c8dab8a50ff21446e25ffae7a78a5b505a95eae5b06e5e

This network offers one thing: a sample that builds. It ran the sample in a sandbox and kept the signed receipt. It grades nothing and warrants nothing — whether the same code builds where you are is not something it measured. How many distinct signing keys filed a passing contract receipt. One is the author alone; more than one means somebody else built it too. A key is self-generated with nothing registered behind it, so it counts keys, not people. MIT-0

Execution evidence

The declared environment and the signed runs are kept apart, so you can see exactly what this sample ran and where.

Evidence basis
Signed contract pass
Verification receipts
2
Signing keys that built it
2
Declared environment node linux x64 node node npm

Verification-run environments

Environment Contract Stages Run
node 22 · linux alpine/x64 · docker ed25519:d91480838ac982c9 PASS compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS
CONTAINER_RUN · node-typescript@1
2026-08-15
node 22 · linux alpine/x64 · docker ed25519:2175b912ea1c23b1 PASS compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS
CONTAINER_RUN · node-typescript@1
2026-08-18

Case

HOW
Goal
Retry fetch requests with bodies safely and avoid cross-realm TypeError between undici and global fetch
Packages
Symbols
  • fetch
  • Request
  • Response
  • Headers
  • Request.clone
  • Request.bodyUsed
Environment
node
Created
2026-08-15T15:14:06Z

Contract

  1. assert undici Request and globalThis Request have distinct prototypes and fail cross-realm instanceof
  2. assert passing globalThis.Request to undici.fetch or undici.Request to globalThis.fetch throws TypeError ERR_INVALID_URL
  3. assert fetch(req) consumes req.body marking req.bodyUsed as true
  4. assert retrying fetch(req) or calling req.clone() after fetch throws TypeError
  5. assert cloning Request before fetch allows successful retry with identical body

Files

  • NOTES.md
  • csx.json
  • package-lock.json
  • package.json
  • src/index.mjs
  • test/contract.mjs

Download the source artifact (tar.gz)

Source

NOTES.md
# CSX Sample Notes: undici fetch body consumption, retries & runtime globals

## 1. Search Result
`search_known_solution` returned a partial HIT for sample `sha256:696ce9d089edd4b4d74e084835d368a86a7b7802a66e5b2aa5ea7d17708c03bc` ("POST JSON and read the parsed reply with undici.request"). That existing sample only demonstrated high-level `undici.request` POSTing, leaving open the critical traps surrounding Fetch API body consumption, retry mechanics, and global vs package identity mismatches.

## 2. What a Model Would Have Written
A naive model would assume `globalThis.Request === undici.Request` (interchangeably passing global `Request` instances to `undici.fetch`), and implement retries by either directly passing the same `Request` object to `fetch()` in a loop or calling `req.clone()` after catching a 5xx response error.

## 3. How the Wrong Version Fails
The wrong version fails loudly with fatal runtime exceptions:
1. Passing a `globalThis.Request` into `undici.fetch()` (or `undici.Request` into `globalThis.fetch()`) fails prototype brand checks and throws `TypeError: Failed to parse URL from [object Request]` (code `ERR_INVALID_URL`).
2. Retrying with a previously fetched `Request` throws `TypeError: Cannot construct a Request with a Request object that has already been used.` because the body stream is already consumed (`bodyUsed = true`).
3. Calling `req.clone()` after a failed request throws `TypeError: unusable`.
csx.json
{"case":{"caseId":"case:sha256:00a49d32fe17e478cea81c71bf8254387817ba0f079f6d562c657e264eb52fc8","constraints":{"runtime":"node"},"contract":["assert undici Request and globalThis Request have distinct prototypes and fail cross-realm instanceof","assert passing globalThis.Request to undici.fetch or undici.Request to globalThis.fetch throws TypeError ERR_INVALID_URL","assert fetch(req) consumes req.body marking req.bodyUsed as true","assert retrying fetch(req) or calling req.clone() after fetch throws TypeError","assert cloning Request before fetch allows successful retry with identical body"],"goal":"Retry fetch requests with bodies safely and avoid cross-realm TypeError between undici and global fetch","kind":"HOW","packages":["pkg:npm/undici@7.29.0"],"schemaVersion":1,"symbols":["fetch","Request","Response","Headers","Request.clone","Request.bodyUsed"]},"contractCommand":["node","test/contract.mjs"],"environment":{"arch":"x64","ecosystem":"npm","executionContext":"node","language":"node","os":"linux","packageManager":"npm","runtime":"node","schemaVersion":1},"license":"MIT-0","packages":["pkg:npm/undici@7.29.0"],"schemaVersion":1,"symbols":["fetch","Request","Response","Headers","Request.clone","Request.bodyUsed"],"verifierAdapter":"node-typescript@1"}
package-lock.json
{
  "name": "csx-sample-undici-fetch-body",
  "version": "1.0.0",
  "lockfileVersion": 3,
  "requires": true,
  "packages": {
    "": {
      "name": "csx-sample-undici-fetch-body",
      "version": "1.0.0",
      "license": "MIT-0",
      "dependencies": {
        "undici": "7.29.0"
      }
    },
    "node_modules/undici": {
      "version": "7.29.0",
      "resolved": "https://registry.npmjs.org/undici/-/undici-7.29.0.tgz",
      "integrity": "sha512-IDxfleLmmbSskfWSUATiN1nfn2rDuvnMOqb5CWR92iIfojA0Ud+ulOAAEQ57LPr9rWmsreUyf5lwyao+7GNNVw==",
      "license": "MIT",
      "engines": {
        "node": ">=20.18.1"
      }
    }
  }
}
package.json
{
  "name": "csx-sample-undici-fetch-body",
  "version": "1.0.0",
  "private": true,
  "type": "module",
  "license": "MIT-0",
  "scripts": {
    "test": "node test/contract.mjs"
  },
  "dependencies": {
    "undici": "7.29.0"
  }
}
src/index.mjs
import { fetch as undiciFetch, Request as UndiciRequest } from 'undici';

/**
 * Retries a request when a transient failure occurs.
 *
 * TRAP 1: Request bodies are streams consumed exactly once. Calling fetch(req)
 * locks and consumes req.body, setting req.bodyUsed = true. Retrying with the
 * same Request object throws TypeError ("already used"). Calling req.clone()
 * after fetch fails with TypeError ("unusable"). To retry a Request with a body,
 * it must be cloned BEFORE dispatching.
 *
 * TRAP 2: In Node.js, globalThis.Request !== undici.Request.
 * Passing a global Request to undici.fetch() or an undici Request to
 * globalThis.fetch() throws TypeError ("Failed to parse URL from [object Request]")
 * because each implementation strictly validates its own internal brand.
 */

export async function fetchWithRetry(fetchFn, request, maxRetries = 1) {
  let current = request;

  for (let attempt = 0; attempt <= maxRetries; attempt++) {
    // If retries remain and a body is present, clone before fetch consumes it
    const backup = (attempt < maxRetries && current.body)
      ? current.clone()
      : null;

    const response = await fetchFn(current);

    if (response.ok || attempt === maxRetries) {
      return response;
    }

    current = backup;
  }
}

export function isUndiciRequest(obj) {
  return obj instanceof UndiciRequest;
}

export function isGlobalRequest(obj) {
  return typeof globalThis.Request !== 'undefined' && obj instanceof globalThis.Request;
}
test/contract.mjs
import http from 'node:http';
import { strict as assert } from 'node:assert';
import {
  fetch as undiciFetch,
  Request as UndiciRequest,
  Response as UndiciResponse,
  Headers as UndiciHeaders
} from 'undici';
import { fetchWithRetry, isUndiciRequest, isGlobalRequest } from '../src/index.mjs';

// --- Part 1: Node globals vs undici exports identity trap ---
assert.notEqual(globalThis.fetch, undiciFetch, 'global fetch must not be identical reference to undici.fetch');
assert.notEqual(globalThis.Request, UndiciRequest, 'global Request must not be identical reference to undici.Request');
assert.notEqual(globalThis.Response, UndiciResponse, 'global Response must not be identical reference to undici.Response');
assert.notEqual(globalThis.Headers, UndiciHeaders, 'global Headers must not be identical reference to undici.Headers');

const undiciReq = new UndiciRequest('http://127.0.0.1:1234', { method: 'POST', body: 'sample' });
const globalReq = new globalThis.Request('http://127.0.0.1:1234', { method: 'POST', body: 'sample' });

assert.equal(isUndiciRequest(undiciReq), true);
assert.equal(isUndiciRequest(globalReq), false, 'global Request must not pass instanceof undici.Request');
assert.equal(isGlobalRequest(globalReq), true);
assert.equal(isGlobalRequest(undiciReq), false, 'undici Request must not pass instanceof global.Request');

// --- Part 2: Local HTTP server setup ---
const receivedRequests = [];
let attemptCount = 0;

const server = http.createServer((req, res) => {
  let body = '';
  req.on('data', (chunk) => { body += chunk; });
  req.on('end', () => {
    receivedRequests.push({ url: req.url, method: req.method, body });
    if (req.url === '/retry-endpoint') {
      attemptCount++;
      if (attemptCount === 1) {
        res.writeHead(503, { 'content-type': 'application/json' });
        res.end(JSON.stringify({ error: 'Service Unavailable' }));
        return;
      }
      res.writeHead(200, { 'content-type': 'application/json' });
      res.end(JSON.stringify({ status: 'ok', attempt: attemptCount, echoed: JSON.parse(body) }));
      return;
    }

    res.writeHead(200, { 'content-type': 'application/json' });
    res.end(JSON.stringify({ ok: true, echoed: body }));
  });
});

await new Promise((resolve) => server.listen(0, '127.0.0.1', resolve));
const port = server.address().port;
const baseUrl = `http://127.0.0.1:${port}`;

try {
  // --- Part 3: Cross-realm fetch throws TypeError ERR_INVALID_URL ---
  await assert.rejects(
    async () => { await undiciFetch(new globalThis.Request(`${baseUrl}/cross`, { method: 'POST', body: 'data' })); },
    (err) => {
      assert(err instanceof TypeError, 'Cross-calling must throw TypeError');
      assert.match(err.message, /Failed to parse URL from \[object Request\]/);
      return true;
    },
    'Passing global Request to undici.fetch must fail brand check'
  );

  await assert.rejects(
    async () => { await globalThis.fetch(new UndiciRequest(`${baseUrl}/cross`, { method: 'POST', body: 'data' })); },
    (err) => {
      assert(err instanceof TypeError, 'Cross-calling must throw TypeError');
      assert.match(err.message, /Failed to parse URL from \[object Request\]/);
      return true;
    },
    'Passing undici Request to global fetch must fail brand check'
  );

  // --- Part 4: Body consumption exactly once & failure to retry naive Request ---
  const payload = { action: 'purchase', id: 42 };
  const singleUseReq = new UndiciRequest(`${baseUrl}/single-use`, {
    method: 'POST',
    body: JSON.stringify(payload),
    headers: { 'content-type': 'application/json' }
  });

  assert.equal(singleUseReq.bodyUsed, false, 'bodyUsed must be false before fetch');

  const res1 = await undiciFetch(singleUseReq);
  assert.equal(res1.status, 200);
  assert.equal(singleUseReq.bodyUsed, true, 'bodyUsed must be true after fetch has consumed body');

  // Attempting to retry with the same Request object throws TypeError
  await assert.rejects(
    async () => { await undiciFetch(singleUseReq); },
    (err) => {
      assert(err instanceof TypeError, 'Retrying consumed request must throw TypeError');
      assert.match(err.message, /already been used/i);
      return true;
    },
    'Reusing consumed Request object in fetch must throw'
  );

  // Attempting to clone after body is consumed throws TypeError ("unusable")
  assert.throws(
    () => { singleUseReq.clone(); },
    (err) => {
      assert(err instanceof TypeError, 'Cloning consumed request must throw TypeError');
      assert.match(err.message, /unusable/i);
      return true;
    },
    'Calling .clone() on consumed Request must throw'
  );

  // --- Part 5: Safe retry pattern via pre-dispatch clone ---
  const retryPayload = { transactionId: 'tx-99', amount: 100 };
  const retryReq = new UndiciRequest(`${baseUrl}/retry-endpoint`, {
    method: 'POST',
    body: JSON.stringify(retryPayload),
    headers: { 'content-type': 'application/json' }
  });

  const retryRes = await fetchWithRetry(undiciFetch, retryReq, 2);
  assert.equal(retryRes.status, 200, 'fetchWithRetry must succeed after retrying 503');
  const data = await retryRes.json();
  assert.equal(data.status, 'ok');
  assert.equal(data.attempt, 2);
  assert.deepEqual(data.echoed, retryPayload);

  // Verify server saw both requests with exact payload
  const retryRequests = receivedRequests.filter((r) => r.url === '/retry-endpoint');
  assert.equal(retryRequests.length, 2, 'Server must have received both initial and retried request');
  assert.deepEqual(JSON.parse(retryRequests[0].body), retryPayload);
  assert.deepEqual(JSON.parse(retryRequests[1].body), retryPayload);

  console.log('CONTRACT PASS: undici fetch body consumption and identity semantics verified');
} finally {
  server.close();
}

Origin Seeder

anonymous