Summary
The daemon (Docker / this branch) logs recurring pubsub errors:
pkc-js:...:pubsubSubscribeOnProvider:error pubsub callback error ... TypeError: terminated
[cause]: BodyTimeoutError: Body Timeout Error (UND_ERR_BODY_TIMEOUT)
at .../@libp2p/http/node_modules/undici/lib/dispatcher/client-h1.js
It does not reproduce when running the published CLI via a host npm install.
Root cause (verified empirically)
An idle long-poll HTTP stream is aborted by undici's default 5-minute bodyTimeout. pkc-js
ships a polyfill that disables this:
// pkc-js/dist/node/runtime/node/polyfill.js
setGlobalDispatcher(new Agent({ bodyTimeout: Number.MAX_SAFE_INTEGER }))
But 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) |
setGlobalDispatcher writes the slot of whichever undici is hoisted to top-level:
- This branch / Docker: top-level undici is 7.25.0 (hoisted for
open-graph-scraper@^7
cheerio@^7); @libp2p/http@^8.0.3 is nested on its own undici 8.x. pkc writes .1;
the helia / @libp2p/http request reads .2 (never set) → default 300s → timeout.
- Host install: top-level undici is 8.x; pkc writes
.2; the @libp2p/http request
reads .2 = pkc's MAX-bodyTimeout agent → no timeout.
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 (helia) path.
Fix
Hoist undici 8.x to top-level (mirroring the working host layout) so pkc's polyfill writes the
.2 slot that the @libp2p/http path reads — add a direct undici@^8 dependency; ^7
consumers (cheerio, open-graph-scraper) keep their own nested 7.x copies.
Likely surfaced by the kubo 0.41→0.42 dependency bump on this branch re-hoisting undici to 7.x.
Summary
The daemon (Docker / this branch) logs recurring pubsub errors:
It does not reproduce when running the published CLI via a host
npm install.Root cause (verified empirically)
An idle long-poll HTTP stream is aborted by undici's default 5-minute
bodyTimeout. pkc-jsships a polyfill that disables this:
But undici changed its global-dispatcher symbol between v7 and v8:
Symbol.for('undici.globalDispatcher.1')Symbol.for('undici.globalDispatcher.2')(.1legacy only)setGlobalDispatcherwrites the slot of whichever undici is hoisted to top-level:open-graph-scraper@^7cheerio@^7);@libp2p/http@^8.0.3is nested on its own undici 8.x. pkc writes.1;the helia /
@libp2p/httprequest reads.2(never set) → default 300s → timeout..2; the@libp2p/httprequestreads
.2= pkc's MAX-bodyTimeout agent → no timeout.The kubo-rpc-client pubsub long-poll itself uses native global
fetch(reads.1) and iscovered by the polyfill; the timing-out request is the undici-8.x /
@libp2p/http(helia) path.Fix
Hoist undici 8.x to top-level (mirroring the working host layout) so pkc's polyfill writes the
.2slot that the@libp2p/httppath reads — add a directundici@^8dependency;^7consumers (cheerio, open-graph-scraper) keep their own nested 7.x copies.
Likely surfaced by the kubo 0.41→0.42 dependency bump on this branch re-hoisting undici to 7.x.