denoland/deno · error · InvalidURLSchemeError
ERR_INVALID_URL_SCHEME
ERR_INVALID_URL_SCHEME
Error message
The URL must be of scheme file:
What it means
node:sqlite's DatabaseSync (and backup()) accept the database location as a string, a Uint8Array, or a URL object — but a URL is only meaningful with the `file:` scheme. parsePath checks `path.protocol !== 'file:'` and throws ERR_INVALID_URL_SCHEME for anything else, because sqlite only opens local files.
Source
Thrown at ext/node/polyfills/sqlite.ts:136
class InvalidStateError extends Error {
code;
constructor(message) {
super(message);
this.code = "ERR_INVALID_STATE";
}
}
const parsePath = (path) => {
let parsedPath;
if (typeof path === "string") {
parsedPath = path;
} else if (isUint8Array(path)) {
const decoder = new TextDecoder("utf8");
parsedPath = decoder.decode(path);
} else if (ObjectPrototypeIsPrototypeOf(URLPrototype, path)) {
if (path.protocol !== "file:") {
throw new InvalidURLSchemeError();
}
parsedPath = path.href;
}
if (
typeof parsedPath === "undefined" ||
StringPrototypeIncludes(parsedPath, "\0")
) {
throw new InvalidArgTypeError(
'The "path" argument must be a string, Uint8Array, or URL without null bytes.',
);
}
return parsedPath;
};
// Using ES5 class allows custom error to be thrown
// when called without `new`.View on GitHub (pinned to 9ad36f7a2c)
Solutions
- Pass a plain filesystem path string instead of a URL
- If you have a URL, keep the file: scheme (`new URL('file:///data/app.db')`) or extract `url.pathname`
- For remote databases, copy/download the file locally first — node:sqlite cannot open remote resources
Example fix
// before
const db = new DatabaseSync(new URL('https://example.com/db.sqlite'));
// ERR_INVALID_URL_SCHEME
// after
const db = new DatabaseSync('/data/db.sqlite');
// or
const db2 = new DatabaseSync(new URL('file:///data/db.sqlite')); Defensive patterns
Strategy: type-guard
Validate before calling
function toSqlitePath(p) {
if (p instanceof URL) {
if (p.protocol !== 'file:') {
throw new TypeError(`node:sqlite requires a file: URL, got ${p.protocol}`);
}
return decodeURIComponent(p.pathname);
}
return p; // string or Uint8Array pass through
}
const db = new DatabaseSync(toSqlitePath(loc)); Type guard
const isFileUrl = (u) => u instanceof URL && u.protocol === 'file:';
Prevention
- Store sqlite locations as plain filesystem paths in configuration
- Validate URL protocol before passing any URL to node:sqlite APIs
- Remember node:sqlite only opens local files — copy remote databases first
When it happens
Trigger: `new DatabaseSync(new URL('http://example.com/db.sqlite'))`, `new DatabaseSync(new URL('sqlite:foo'))`, or any non-file URL passed as the first argument (also as the `path` argument to `backup(db, url)`).
Common situations: Config-driven apps that build a single URL and pass it to both fetch() and sqlite; 'upgrading' a plain path to a URL during a better-sqlite3 migration; remote DSN strings (postgres://, https://) reused for a local cache DB.
Related errors
- ERR_INVALID_URL
- ERR_HTTP2_UNSUPPORTED_PROTOCOL
- ERR_INVALID_URL
- ERR_INVALID_ARG_TYPE
- ERR_CONSTRUCT_CALL_REQUIRED
AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20).
Data as JSON: /api/errors/399cb26c8cfef4fa.
Report an issue: GitHub.