Skip to content

[wrangler] fix: patch undici to prevent fetch() throwing on 401 responses with a request body#13058

Merged
petebacondarwin merged 1 commit intomainfrom
pbd/fix-undici-401-body-source
Mar 26, 2026
Merged

[wrangler] fix: patch undici to prevent fetch() throwing on 401 responses with a request body#13058
petebacondarwin merged 1 commit intomainfrom
pbd/fix-undici-401-body-source

Conversation

@petebacondarwin
Copy link
Copy Markdown
Contributor

@petebacondarwin petebacondarwin commented Mar 25, 2026

Fixes #12967.

Unstable_DevWorker.fetch() (and any other use of undici's fetch in wrangler) throws TypeError: fetch failed with cause expected non-null body source whenever a request with a body receives a 401 response.

Root cause

isTraversableNavigable() in undici 7.24.4 unconditionally returns true — a stub left in place from nodejs/undici#4747. This causes the 401 credential-retry block in httpNetworkOrCacheFetch to always execute, even in Node.js where there is no browser UI to prompt users for credentials. When the request body's source is null (which happens when a Request object is passed as the init argument to fetch()), the retry block immediately throws makeNetworkError('expected non-null body source').

The earlier fix in nodejs/undici#4761 (v7.19.1) added a return response to prevent an infinite retry loop, but that code is unreachable in this case — the body.source == null guard fires first.

This is tracked upstream as nodejs/undici#4910 with no fix in progress yet.

Fix

Apply a pnpm patch to undici that changes isTraversableNavigable() to return false. In Node.js there is no traversable navigable (no browser tab), so the 401-retry block should never be entered. This is a one-line change that exactly mirrors the correct upstream fix and can be removed once a patched undici version is released.


  • Tests
    • Tests included/updated
    • Automated tests not possible - manual testing has been completed as follows:
    • Additional testing not necessary because: this is a patch to an upstream bug with a clear, targeted fix verified by build inspection (the bundled cli.js now has isTraversableNavigable returning false)
  • Public documentation
    • Documentation not necessary because: this is a bug fix with no API changes

Open with Devin

… request body

isTraversableNavigable() in undici 7.24.4 unconditionally returns true, causing the
401 credential-retry block in httpNetworkOrCacheFetch to always execute in Node.js.
When the request body source is null (e.g. when passing a Request object as fetch init),
this throws 'expected non-null body source'. Tracked upstream in nodejs/undici#4910.

Workaround: apply a pnpm patch that returns false from isTraversableNavigable(),
preventing the retry block from ever entering in Node.js where there is no browser UI
to prompt for credentials.

Fixes: #12967
@petebacondarwin petebacondarwin requested a review from a team as a code owner March 25, 2026 20:38
@petebacondarwin petebacondarwin requested a review from NuroDev March 25, 2026 20:38
@github-project-automation github-project-automation bot moved this to Untriaged in workers-sdk Mar 25, 2026
@workers-devprod
Copy link
Copy Markdown
Contributor

workers-devprod commented Mar 25, 2026

Codeowners approval required for this PR:

  • ✅ @cloudflare/wrangler
Show detailed file reviewers

@github-actions
Copy link
Copy Markdown
Contributor

✅ All changesets look good

@ask-bonk
Copy link
Copy Markdown
Contributor

ask-bonk bot commented Mar 25, 2026

I've reviewed the full diff. Here's my analysis:

  1. Patch correctness: The one-line change (return true -> return false) in isTraversableNavigable() is exactly right. In Node.js there is no traversable navigable (browser tab/window), so this function should always return false. The upstream issue Providing a request body when the response is 401 fails nodejs/undici#4910 is confirmed open.

  2. Patch scope: The patch is minimal and surgical -- it only touches the single function that has the incorrect stub behavior.

  3. Changeset: Properly formatted as a patch for wrangler, with a clear description and upstream references.

  4. package.json: The patchedDependencies entry correctly pins to undici@7.24.4 matching the version in use.

  5. pnpm-lock.yaml: All the lockfile changes are mechanical -- just adding the (patch_hash=eoxacwyrfksebemwxidpujesci) suffix to every resolved undici@7.24.4 entry. These are auto-generated by pnpm.

  6. Version pinning concern: The patch is pinned to undici@7.24.4. If undici is updated, the patch will no longer apply, which is the desired behavior (the patch should be removed once upstream fixes the issue). The version specifier in pnpm-workspace.yaml (via catalog) controls the version used.

No logic bugs, no security issues, no backward compatibility concerns. This is a straightforward, well-documented workaround for an upstream bug.

LGTM

github run

Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no potential bugs to report.

View in Devin Review to see 2 additional findings.

Open in Devin Review

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new bot commented Mar 25, 2026

create-cloudflare

npm i https://pkg.pr.new/create-cloudflare@13058

@cloudflare/kv-asset-handler

npm i https://pkg.pr.new/@cloudflare/kv-asset-handler@13058

miniflare

npm i https://pkg.pr.new/miniflare@13058

@cloudflare/pages-shared

npm i https://pkg.pr.new/@cloudflare/pages-shared@13058

@cloudflare/unenv-preset

npm i https://pkg.pr.new/@cloudflare/unenv-preset@13058

@cloudflare/vite-plugin

npm i https://pkg.pr.new/@cloudflare/vite-plugin@13058

@cloudflare/vitest-pool-workers

npm i https://pkg.pr.new/@cloudflare/vitest-pool-workers@13058

@cloudflare/workers-editor-shared

npm i https://pkg.pr.new/@cloudflare/workers-editor-shared@13058

wrangler

npm i https://pkg.pr.new/wrangler@13058

commit: 1f5f680

@petebacondarwin petebacondarwin requested review from edmundhung and removed request for NuroDev March 25, 2026 20:58
@CMCDragonkai
Copy link
Copy Markdown

I just hit this on wrangler 4.77. Will this on the next version release?

@github-project-automation github-project-automation bot moved this from Untriaged to Approved in workers-sdk Mar 26, 2026
beanow-at-crabnebula added a commit to beanow-at-crabnebula/undici-401-request-body that referenced this pull request Mar 26, 2026
@beanow-at-crabnebula
Copy link
Copy Markdown

👍 I've tried the preview build on the reproduction repo.
Looks to resolve the issue.

beanow-at-crabnebula/undici-401-request-body@48292f0

@petebacondarwin petebacondarwin merged commit 992f9a3 into main Mar 26, 2026
60 of 64 checks passed
@petebacondarwin petebacondarwin deleted the pbd/fix-undici-401-body-source branch March 26, 2026 11:30
@github-project-automation github-project-automation bot moved this from Approved to Done in workers-sdk Mar 26, 2026
@CMCDragonkai
Copy link
Copy Markdown

I just hit this on wrangler 4.77. Will this on the next version release?

Just a note, 4.78 doesn't fix this in when testing with unstable_startWorker.

The fix is present in bundled wrangler-dist/cli.js, but the local Miniflare path is resolving a separate unpatched external undici.

So miniflare is unpatched even if wrangler/cli.js is patched.

@petebacondarwin
Copy link
Copy Markdown
Contributor Author

Yeah I was just thinking about that yesterday. I'll work on a better fix.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

Unstable_DevWorker.fetch fails when request has a body and receives a 401 response

6 participants