Is there an existing issue for this?
Searched for fileURLToPath, must be of scheme file, code-transformer-bundler-plugins, and jsdom/happy-dom combinations before filing; nothing matched. #22794 and #23611 look like sibling symptoms of the same structural cause — the server entry eagerly pulling in the orchestrion bundler plugin — but neither covers this crash.
How do you use Sentry?
Sentry SaaS (sentry.io)
Which SDK are you using?
@sentry/nextjs
SDK Version
10.72.0 and 10.73.0 (10.71.0 is fine)
Framework Version
Next.js 16.3.3, Node 24.14.0. Reproduces with no framework at all — see below.
Link to Sentry event
N/A — this is a module-load crash, nothing reaches Sentry.
Reproduction Example/SDK Setup
Importing @sentry/nextjs throws at module scope whenever a document global exists — which is the normal state of affairs under jsdom or happy-dom, i.e. in any Vitest or Jest test using a DOM environment.
No test runner or bundler is needed to see it:
mkdir sentry-repro && cd sentry-repro && npm init -y
npm i @sentry/nextjs@10.73.0
cat > repro.cjs <<'JS'
globalThis.document = { baseURI: 'http://localhost:3000/' }
require('@sentry/nextjs')
console.log('loaded OK')
JS
node repro.cjs # throws
node -e "require('@sentry/nextjs')" # control: prints loaded OK
Steps to Reproduce
- Install
@sentry/nextjs@10.72.0 or @10.73.0.
- Define any
document global with a baseURI — or just run a Vitest suite with environment: 'happy-dom' (or Jest with testEnvironment: 'jsdom') that imports the SDK, directly or transitively.
- Load the module.
Expected Result
The module loads. 10.71.0 does, under an identical setup.
Actual Result
TypeError [ERR_INVALID_URL_SCHEME]: The URL must be of scheme file
at Object.fileURLToPath (node:internal/url:1608:11)
at Module.<anonymous> (node_modules/@sentry/server-utils/build/cjs/vendored/
@apm-js-collab/code-transformer-bundler-plugins/dist/esm/webpack.js:9:61)
at Module._compile (node:internal/modules/cjs/loader:1812:14)
The node export condition of @sentry/nextjs reaches @sentry/server-utils/build/cjs/orchestrion/bundler/webpack.js, which pulls in the vendored @apm-js-collab/code-transformer-bundler-plugins. That module computes LOADER_PATH at module scope from a dual browser/Node guard:
var LOADER_PATH = path.resolve(path.dirname(url.fileURLToPath(
typeof document === 'undefined'
? pathToFileURL(__filename).href
: (_documentCurrentScript && ... || new URL('vendored/.../webpack.js', document.baseURI).href)
)), "..", "cjs", "webpack-loader.cjs");
The guard is typeof document === 'undefined', so it treats "a document exists" as "this is a browser". Under jsdom/happy-dom that is false — the code is running in Node, and __filename is right there and valid. It takes the browser branch, builds http://localhost:3000/vendored/... from document.baseURI, and hands that to fileURLToPath, which only accepts file:.
Two things make this worse than it might look:
- It throws at module scope, so it is not catchable by the importer and takes down the whole module graph. In our suite, 11 test files stopped loading; every assertion inside them still passed, so the failure did not look like a dependency problem at all.
- It arrives through lockfile regeneration, not a reviewed bump. Our
package.json says ^10.70.0 and never changed; a routine Dependabot PR for unrelated packages re-resolved the tree and moved the SDK from 10.71.0 to 10.72.0 as a side effect.
Suggested fix
Prefer a positive Node check over an absence-of-document check, e.g. gate on typeof __filename !== 'undefined' (or process.versions?.node) first and fall back to the document-based path only when there is genuinely no module path available. The bundler emitting the dual guard is @apm-js-collab/code-transformer-bundler-plugins, so the fix may belong there rather than in this repo — but it ships vendored inside @sentry/server-utils, which is where it reaches users.
Deferring the LOADER_PATH computation until the plugin is actually used would also fix it, and would additionally address the class of problem in #22794 and #23611: a bundler-time plugin should not be doing filesystem path resolution just because someone imported the SDK.
Workaround
Pinning below 10.72.0 ("@sentry/nextjs": "<10.72.0" in pnpm.overrides). Setting resolve.conditions: ['browser'] in Vitest also gets past it, but only by resolving the client build, which then wants next/router — absent in an App Router project — and it changes resolution for every other package too.
Is there an existing issue for this?
Searched for
fileURLToPath,must be of scheme file,code-transformer-bundler-plugins, and jsdom/happy-dom combinations before filing; nothing matched. #22794 and #23611 look like sibling symptoms of the same structural cause — the server entry eagerly pulling in the orchestrion bundler plugin — but neither covers this crash.How do you use Sentry?
Sentry SaaS (sentry.io)
Which SDK are you using?
@sentry/nextjs
SDK Version
10.72.0 and 10.73.0 (10.71.0 is fine)
Framework Version
Next.js 16.3.3, Node 24.14.0. Reproduces with no framework at all — see below.
Link to Sentry event
N/A — this is a module-load crash, nothing reaches Sentry.
Reproduction Example/SDK Setup
Importing
@sentry/nextjsthrows at module scope whenever adocumentglobal exists — which is the normal state of affairs under jsdom or happy-dom, i.e. in any Vitest or Jest test using a DOM environment.No test runner or bundler is needed to see it:
Steps to Reproduce
@sentry/nextjs@10.72.0or@10.73.0.documentglobal with abaseURI— or just run a Vitest suite withenvironment: 'happy-dom'(or Jest withtestEnvironment: 'jsdom') that imports the SDK, directly or transitively.Expected Result
The module loads. 10.71.0 does, under an identical setup.
Actual Result
The
nodeexport condition of@sentry/nextjsreaches@sentry/server-utils/build/cjs/orchestrion/bundler/webpack.js, which pulls in the vendored@apm-js-collab/code-transformer-bundler-plugins. That module computesLOADER_PATHat module scope from a dual browser/Node guard:The guard is
typeof document === 'undefined', so it treats "adocumentexists" as "this is a browser". Under jsdom/happy-dom that is false — the code is running in Node, and__filenameis right there and valid. It takes the browser branch, buildshttp://localhost:3000/vendored/...fromdocument.baseURI, and hands that tofileURLToPath, which only acceptsfile:.Two things make this worse than it might look:
package.jsonsays^10.70.0and never changed; a routine Dependabot PR for unrelated packages re-resolved the tree and moved the SDK from 10.71.0 to 10.72.0 as a side effect.Suggested fix
Prefer a positive Node check over an absence-of-
documentcheck, e.g. gate ontypeof __filename !== 'undefined'(orprocess.versions?.node) first and fall back to thedocument-based path only when there is genuinely no module path available. The bundler emitting the dual guard is@apm-js-collab/code-transformer-bundler-plugins, so the fix may belong there rather than in this repo — but it ships vendored inside@sentry/server-utils, which is where it reaches users.Deferring the
LOADER_PATHcomputation until the plugin is actually used would also fix it, and would additionally address the class of problem in #22794 and #23611: a bundler-time plugin should not be doing filesystem path resolution just because someone imported the SDK.Workaround
Pinning below 10.72.0 (
"@sentry/nextjs": "<10.72.0"inpnpm.overrides). Settingresolve.conditions: ['browser']in Vitest also gets past it, but only by resolving the client build, which then wantsnext/router— absent in an App Router project — and it changes resolution for every other package too.