Version: superdoc@2.3.0 (@superdoc/docx-engine@0.2.0); the same resolution ships in 2.4.0-next (@superdoc/docx-engine@0.3.0-next.18).
Config: document.v2Collaboration = { providerType: 'liveblocks', documentId, authEndpoint, roomMode } (string authEndpoint — the server-auth mode).
What happens
- The collaboration worker starts and completes its hello handshake.
- No HTTP request is ever issued to the
authEndpoint (and none to *.liveblocks.io).
- After 10s the host fails the open:
WorkerTransportError: v2 collaboration sync timed out after 10000ms (phase: 'worker.open_error', reason: 'open-session-failed').
So authEndpoint-based collaboration is unusable in the browser. publicApiKey avoids it but forfeits server-side authorization.
Root cause
Collaboration is worker-only, and the vendored @liveblocks/client lives in dist/assets/collaboration-worker-entry-*.js. Its auth manager resolves the fetcher as (verbatim from @liveblocks/core):
polyfills?.fetch ?? (typeof window === "undefined" ? undefined : window.fetch)
The worker adapter's createClient({ authEndpoint }) call site passes no polyfills, and in a DedicatedWorkerGlobalScope window is undefined — so a string authEndpoint throws Liveblocks' StopRetrying("…you need to provide a fetch polyfill.") inside the worker before any request. The host only ever sees the sync timeout.
Runnable proof against the shipped package (npm i superdoc@2.3.0, then node verify.mjs):
import { readFile, readdir } from 'node:fs/promises'
const dir = 'node_modules/@superdoc/docx-engine/dist/assets'
const entry = (await readdir(dir)).find((f) => f.startsWith('collaboration-worker-entry') && f.endsWith('.js'))
const src = await readFile(`${dir}/${entry}`, 'utf-8')
console.log('window-gated fetcher present:', src.includes("typeof window>'u'?void 0x0:window['fetch']"))
console.log('fetch-polyfill failure string present:', src.includes('fetch\\x20polyfill'))
Both print true on 2.3.0.
Fix (verified)
Either pass the polyfill at the call site:
createClient({ authEndpoint, polyfills: { fetch: globalThis.fetch.bind(globalThis) } })
or fall back to globalThis.fetch at the resolution site. We patched the shipped worker bundle with exactly that one-line change (typeof window>'u' ? globalThis.fetch?.bind(globalThis) : window.fetch) and authEndpoint collaboration authenticates, opens rooms, and syncs correctly in Chrome (verified end-to-end with a Next.js app and a standard Liveblocks ID-token auth endpoint — two clients converge, presence works).
Version:
superdoc@2.3.0(@superdoc/docx-engine@0.2.0); the same resolution ships in2.4.0-next(@superdoc/docx-engine@0.3.0-next.18).Config:
document.v2Collaboration = { providerType: 'liveblocks', documentId, authEndpoint, roomMode }(stringauthEndpoint— the server-auth mode).What happens
authEndpoint(and none to*.liveblocks.io).WorkerTransportError: v2 collaboration sync timed out after 10000ms(phase: 'worker.open_error',reason: 'open-session-failed').So
authEndpoint-based collaboration is unusable in the browser.publicApiKeyavoids it but forfeits server-side authorization.Root cause
Collaboration is worker-only, and the vendored
@liveblocks/clientlives indist/assets/collaboration-worker-entry-*.js. Its auth manager resolves the fetcher as (verbatim from@liveblocks/core):The worker adapter's
createClient({ authEndpoint })call site passes nopolyfills, and in aDedicatedWorkerGlobalScopewindowis undefined — so a stringauthEndpointthrows Liveblocks'StopRetrying("…you need to provide a fetch polyfill.")inside the worker before any request. The host only ever sees the sync timeout.Runnable proof against the shipped package (
npm i superdoc@2.3.0, thennode verify.mjs):Both print
trueon 2.3.0.Fix (verified)
Either pass the polyfill at the call site:
or fall back to
globalThis.fetchat the resolution site. We patched the shipped worker bundle with exactly that one-line change (typeof window>'u' ? globalThis.fetch?.bind(globalThis) : window.fetch) andauthEndpointcollaboration authenticates, opens rooms, and syncs correctly in Chrome (verified end-to-end with a Next.js app and a standard Liveblocks ID-token auth endpoint — two clients converge, presence works).