Error [ERR_UNSUPPORTED_ESM_URL_SCHEME]: Only URLs with a scheme in: file, data, and node are supported by the default ESM loader. On Windows, absolute paths must be valid file:// URLs. Received protocol 'c:'
Detailed error message
> my-project@1.0.0 start
> tsx --import module-alias/register index.js
node:internal/modules/run_main:107
triggerUncaughtException(
^
Error [ERR_UNSUPPORTED_ESM_URL_SCHEME]: Only URLs with a scheme in: file, data, and node are supported by the default ESM loader. On Windows, absolute paths must be valid file:// URLs. Received protocol 'c:'
at throwIfUnsupportedURLScheme (node:internal/modules/esm/load:195:11)
at defaultLoad (node:internal/modules/esm/load:78:3)
at nextLoad (node:internal/modules/esm/hooks:769:28)
at load (file:///C:/Users/myself/git/my-project/node_modules/tsx/dist/esm/index.mjs?1775534279488:2:1777)
at nextLoad (node:internal/modules/esm/hooks:769:28)
at AsyncLoaderHooksOnLoaderHookWorker.load (node:internal/modules/esm/hooks:406:26)
at handleMessage (node:internal/modules/esm/worker:251:24)
at Immediate.checkForMessages (node:internal/modules/esm/worker:193:28)
at process.processImmediate (node:internal/timers:504:21) {
code: 'ERR_UNSUPPORTED_ESM_URL_SCHEME'
}
Node.js v25.9.0
Package Version
It works fine in module-alias 2.2.3
It breaks in module-alias 2.3.0 - 2.3.4
My environment
Windows 11
node -v
v25.9.0
npm -v
11.12.1
type package.json | findstr "module-alias\""
"module-alias": "^2.3.4",
type package.json | findstr "\"tsx\""
"tsx": "^4.21.0"
What does AI say?
path.join() on Windows returns a Windows backslash path like C:\Users\myself...\node_modules\bcrypt. When that bare Windows path is returned from the resolve hook back into Node's ESM loader, it's treated as a URL with . as the scheme — which ESM refuses to load.
The resolveAlias function needs to convert the result to a URL string before returning it. The import for pathToFileURL is already there at the top of the file but is never used by this branch.
Here's exactly what's wrong and where:
File: esm-loader.mjs:93
Problem: The resolver returns a raw Windows path (e.g. C:...\bcrypt) from all three return sites, but the ESM resolve hook must return either a bare specifier or a valid URL. Node 25 triggers the bug here because it enforces this strictly.
The pathToFileURL import on line 6 exists but is unused — it should wrap every returned path.
This is a bug in module-alias@2.3.4's ESM loader on Windows with Node 25. Node < 25 was more lenient about bare Windows paths reaching the loader; Node 25 is strict.
Not sure about AI's claim for the Node.js version since it works with the same Node.js when I downgrade to the module-alias version 2.2.3.
Error [ERR_UNSUPPORTED_ESM_URL_SCHEME]: Only URLs with a scheme in: file, data, and node are supported by the default ESM loader. On Windows, absolute paths must be valid file:// URLs. Received protocol 'c:'
Detailed error message
Package Version
It works fine in module-alias 2.2.3
It breaks in module-alias 2.3.0 - 2.3.4
My environment
What does AI say?
Not sure about AI's claim for the Node.js version since it works with the same Node.js when I downgrade to the module-alias version 2.2.3.