Skip to content

fix(deps): pin undici@8 so pkc-js body-timeout polyfill covers @libp2p/http (#84)#85

Merged
Rinse12 merged 1 commit into
masterfrom
fix/undici-8-global-dispatcher-hoisting
Jun 9, 2026
Merged

fix(deps): pin undici@8 so pkc-js body-timeout polyfill covers @libp2p/http (#84)#85
Rinse12 merged 1 commit into
masterfrom
fix/undici-8-global-dispatcher-hoisting

Conversation

@Rinse12

@Rinse12 Rinse12 commented Jun 9, 2026

Copy link
Copy Markdown
Member

Problem

The daemon logs recurring pubsub errors in Docker (not on a host npm install):

pkc-js:...:pubsubSubscribeOnProvider:error pubsub callback error ... TypeError: terminated
[cause]: BodyTimeoutError (UND_ERR_BODY_TIMEOUT)  at .../@libp2p/http/node_modules/undici/...

Root cause

undici changed its global-dispatcher symbol between v7 and v8:

undici get/setGlobalDispatcher slot
7.x Symbol.for('undici.globalDispatcher.1')
8.x Symbol.for('undici.globalDispatcher.2') (.1 legacy only)

pkc-js disables undici's default 5-minute bodyTimeout for idle pubsub long-polls via
setGlobalDispatcher(new Agent({ bodyTimeout: MAX })), importing the top-level undici —
so it writes the slot of whatever version is hoisted to top.

  • Before: cheerio/open-graph-scraper (undici@^7) won the top-level hoist → undici
    7.25.0 on top → pkc writes .1. The helia/@libp2p/http path uses undici 8.x and
    reads .2 (never set) → default 300s body timeout → idle pubsub streams aborted at 5 min.
  • Host installs happened to hoist undici 8.x → pkc wrote .2 → no timeout. Hence
    "Docker only".

(The kubo-rpc-client pubsub long-poll itself uses native global fetch, reads .1, and is
covered by the polyfill — the timing-out request is the undici-8.x / @libp2p/http path.)

Fix

Pin a direct undici@8.4.1 so 8.x wins the top-level hoist (mirroring the working host
layout). Result:

  • top-level undici → 8.4.1
  • @libp2p/http → deduped to top-level 8.4.1 (no nested copy)
  • cheerio / open-graph-scraper → keep their own nested 7.x

pkc-js's polyfill now writes the .2 slot the @libp2p/http path reads → idle pubsub
streams inherit bodyTimeout: MAX.

Verification

  • Container probes against the dependency tree: pre-fix, a top-level-7.x setGlobalDispatcher
    did not govern an undici-8.x request; post-fix it does.
  • Regression test test/cli/undici-dispatcher-hoisting.test.ts (red on the 7.25.0/8.2.0
    split, green now).
  • npm run build, npm run build:test, and full npm run test:cli pass (29 files, 211
    passed, 1 skipped).

Closes #84

Summary by CodeRabbit

Release Notes

Dependencies

  • Added undici v8.4.1 as a dependency to improve HTTP request handling and client compatibility.

…p/http

Top-level undici was hoisted to 7.x (to satisfy cheerio/open-graph-scraper),
but undici changed its global-dispatcher symbol between v7 (undici.globalDispatcher.1)
and v8 (.2). pkc-js's setGlobalDispatcher(bodyTimeout: MAX) polyfill writes the slot
of whichever undici is hoisted to top-level, while the helia/@libp2p/http path
(undici 8.x) reads the .2 slot. With undici 7.x on top, pkc writes .1, @libp2p/http
reads an unset .2, and idle pubsub long-poll streams hit undici's default 5-minute
bodyTimeout -> UND_ERR_BODY_TIMEOUT (reproducible in Docker, not on host installs
where undici 8.x hoists to top).

Pin a direct undici@8.4.1 so 8.x wins the top-level hoist (cheerio/open-graph-scraper
keep their own nested 7.x); pkc's polyfill then writes .2 and @libp2p/http inherits
bodyTimeout: MAX. Adds a regression test asserting top-level undici is major >= 8 and
that @libp2p/http resolves to the same major.

Refs #84
@coderabbitai

coderabbitai Bot commented Jun 9, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

Pull request was closed or merged during review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 3aa3dac8-d7b8-408c-9432-e45752370e39

📥 Commits

Reviewing files that changed from the base of the PR and between 67d2eb1 and fc76c35.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (2)
  • package.json
  • test/cli/undici-dispatcher-hoisting.test.ts

📝 Walkthrough

Walkthrough

This PR hoists undici@8.4.1 as a direct dependency to resolve a pubsub body-timeout issue where pkc-js's global-dispatcher polyfill and @libp2p/http's nested undici were using different symbol slots due to the undici v7–v8 global-dispatcher symbol change. Regression tests verify that both top-level and nested undici major versions match.

Changes

Undici v8 hoisting for global-dispatcher symbol alignment

Layer / File(s) Summary
Undici 8.x direct dependency addition
package.json
Adds undici@8.4.1 to dependencies, hoisting the v8 symbol slot (.2) to top-level where pkc-js's bodyTimeout polyfill writes.
Global-dispatcher symbol hoisting regression test
test/cli/undici-dispatcher-hoisting.test.ts
Regression suite verifies top-level undici is v8+ and that @libp2p/http's nested undici resolves to the same major version, ensuring symbol slot alignment between pkc-js's polyfill and the helia request path.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐰 A symbol slot was split in twain,
Between the v8 and v7 chain.
We hoist the eight to claim the crown,
So timeout polyfills won't let us down! 🚀

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: pinning undici@8 to ensure the pkc-js body-timeout polyfill covers @libp2p/http, directly addressing the linked issue.
Linked Issues check ✅ Passed The PR fully addresses all coding objectives from issue #84: pinning undici@8.4.1 in dependencies, hoisting undici 8.x top-level, and adding regression tests to verify the fix.
Out of Scope Changes check ✅ Passed All changes are directly scoped to the linked issue: adding undici@8.4.1 dependency and a regression test suite verifying the hoisting behavior.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/undici-8-global-dispatcher-hoisting

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

test/cli/undici-dispatcher-hoisting.test.ts

Oops! Something went wrong! :(

ESLint: 8.27.0

Error: ESLint configuration in --config » eslint-config-oclif is invalid:

  • Unexpected top-level property "__esModule".

Referenced from: /.eslintrc
at ConfigValidator.validateConfigSchema (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2156:19)
at ConfigArrayFactory._normalizeConfigData (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2998:19)
at ConfigArrayFactory._loadConfigData (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2963:21)
at ConfigArrayFactory._loadExtendedShareableConfig (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3264:21)
at ConfigArrayFactory._loadExtends (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3135:25)
at ConfigArrayFactory._normalizeObjectConfigDataBody (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3074:25)
at _normalizeObjectConfigDataBody.next ()
at ConfigArrayFactory._normalizeObjectConfigData (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:3019:20)
at _normalizeObjectConfigData.next ()
at ConfigArrayFactory.loadFile (/node_modules/@eslint/eslintrc/dist/eslintrc.cjs:2829:16)


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@Rinse12 Rinse12 merged commit 90af8c4 into master Jun 9, 2026
3 of 4 checks passed
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.

Pubsub UND_ERR_BODY_TIMEOUT in Docker: undici 7→8 global-dispatcher symbol split

1 participant