denoland/deno · error · TypeError
ERR_INVALID_URL_SCHEME
ERR_INVALID_URL_SCHEME
Error message
The URL must be of scheme file
What it means
fileURLToPath() only converts file: URLs — after the type check, any other scheme throws ERR_INVALID_URL_SCHEME ('The URL must be of scheme file'). In Deno this is common: modules imported from https:// have an https import.meta.url, which cannot be mapped to a filesystem path.
Source
Thrown at ext/node/polyfills/url.ts:1378
* @see https://www.rfc-editor.org/rfc/rfc3490#section-4
*/
function domainToUnicode(domain: string) {
return idnaToUnicode(domain);
}
/**
* This function ensures the correct decodings of percent-encoded characters as well as ensuring a cross-platform valid absolute path string.
* @see Tested in `parallel/test-fileurltopath.js`.
* @param path The file URL string or URL object to convert to a path.
* @returns The fully-resolved platform-specific Node.js file path.
*/
function fileURLToPath(path: string | URL): string {
if (typeof path === "string") path = new URL(path);
else if (!ObjectPrototypeIsPrototypeOf(URL.prototype, path)) {
throw new ERR_INVALID_ARG_TYPE("path", ["string", "URL"], path);
}
if (path.protocol !== "file:") {
throw new ERR_INVALID_URL_SCHEME("file");
}
return isWindows ? getPathFromURLWin(path) : getPathFromURLPosix(path);
}
// https://url.spec.whatwg.org/#percent-decode
function isHexCharByte(byte: number): boolean {
// 0-9 A-F a-f
return (byte >= 0x30 && byte <= 0x39) || (byte >= 0x41 && byte <= 0x46) ||
(byte >= 0x61 && byte <= 0x66);
}
function hexByteToNumber(byte: number): number {
return (
// 0-9
byte >= 0x30 && byte <= 0x39
? (byte - 48)
// Convert to uppercase: ((byte & 0xDF) - 65) + 10
: ((byte & 0xDF) - 55)View on GitHub (pinned to 9ad36f7a2c)
Solutions
- Branch on protocol: `if (new URL(u).protocol === 'file:')` convert, else handle remotely
- For remote modules, fetch() assets instead of reading the filesystem
- Use `import.meta.url.startsWith('file:')` as a cheap pre-check before deriving paths
Example fix
// before
const dir = path.dirname(fileURLToPath(import.meta.url)); // throws for https modules
// after
const dir = import.meta.url.startsWith("file:")
? path.dirname(fileURLToPath(import.meta.url))
: "."; // remote module: fall back to cwd or fetch assets Defensive patterns
Strategy: validation
Validate before calling
const u = typeof input === "string" ? new URL(input) : input;
if (u.protocol !== "file:") {
throw new Error(`expected a file: URL, got ${u.protocol}`);
}
return fileURLToPath(u); Type guard
const isFileUrl = (v: string | URL): boolean => (typeof v === "string" ? new URL(v) : v).protocol === "file:";
Try / catch
try {
p = fileURLToPath(import.meta.url);
} catch (e: any) {
if (e?.code === "ERR_INVALID_URL_SCHEME") {
p = "."; // remote module: no local file, fall back to cwd or fetch
} else {
throw e;
}
} Prevention
- Gate path derivation on import.meta.url.startsWith('file:')
- Serve remote-module assets via fetch(), not fs
- Centralize protocol checks in one path helper
When it happens
Trigger: `fileURLToPath('https://example.com/mod.ts')`; `fileURLToPath(import.meta.url)` inside a remotely imported module; passing data: or http: URLs.
Common situations: Deno scripts importing from the network; code shared between local and remote module execution; build tools that feed bundle or asset URLs into path helpers.
Related errors
- ERR_INVALID_URL
- ERR_INVALID_URL_SCHEME
- Can't convert url ("{}") to filename.
- Can't convert url ("{}") to filename.
- Empty filepath.
AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20).
Data as JSON: /api/errors/bfe7838027440c42.
Report an issue: GitHub.