{"record":{"id":"399cb26c8cfef4fa","repo":"denoland/deno","slug":"err-invalid-url-scheme","errorCode":"ERR_INVALID_URL_SCHEME","errorMessage":"The URL must be of scheme file:","messagePattern":"The URL must be of scheme file:","errorType":"validation","errorClass":"InvalidURLSchemeError","httpStatus":null,"severity":"error","filePath":"ext/node/polyfills/sqlite.ts","lineNumber":136,"sourceCode":"\nclass InvalidStateError extends Error {\n  code;\n  constructor(message) {\n    super(message);\n    this.code = \"ERR_INVALID_STATE\";\n  }\n}\n\nconst parsePath = (path) => {\n  let parsedPath;\n  if (typeof path === \"string\") {\n    parsedPath = path;\n  } else if (isUint8Array(path)) {\n    const decoder = new TextDecoder(\"utf8\");\n    parsedPath = decoder.decode(path);\n  } else if (ObjectPrototypeIsPrototypeOf(URLPrototype, path)) {\n    if (path.protocol !== \"file:\") {\n      throw new InvalidURLSchemeError();\n    }\n    parsedPath = path.href;\n  }\n\n  if (\n    typeof parsedPath === \"undefined\" ||\n    StringPrototypeIncludes(parsedPath, \"\\0\")\n  ) {\n    throw new InvalidArgTypeError(\n      'The \"path\" argument must be a string, Uint8Array, or URL without null bytes.',\n    );\n  }\n\n  return parsedPath;\n};\n\n// Using ES5 class allows custom error to be thrown\n// when called without `new`.","sourceCodeStart":118,"sourceCodeEnd":154,"githubUrl":"https://github.com/denoland/deno/blob/9ad36f7a2cce60488e6ec52283efb32efddaf93a/ext/node/polyfills/sqlite.ts#L118-L154","documentation":"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.","triggerScenarios":"`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)`).","commonSituations":"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.","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"],"exampleFix":"// before\nconst db = new DatabaseSync(new URL('https://example.com/db.sqlite'));\n// ERR_INVALID_URL_SCHEME\n\n// after\nconst db = new DatabaseSync('/data/db.sqlite');\n// or\nconst db2 = new DatabaseSync(new URL('file:///data/db.sqlite'));","handlingStrategy":"type-guard","validationCode":"function toSqlitePath(p) {\n  if (p instanceof URL) {\n    if (p.protocol !== 'file:') {\n      throw new TypeError(`node:sqlite requires a file: URL, got ${p.protocol}`);\n    }\n    return decodeURIComponent(p.pathname);\n  }\n  return p; // string or Uint8Array pass through\n}\nconst db = new DatabaseSync(toSqlitePath(loc));","typeGuard":"const isFileUrl = (u) => u instanceof URL && u.protocol === 'file:';","tryCatchPattern":null,"preventionTips":["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"],"tags":["sqlite","url","node-compat"],"backgroundTag":"invalid-url-scheme","analyzedSha":"9ad36f7a2cce60488e6ec52283efb32efddaf93a","analyzedAt":"2026-08-20T13:07:44.778Z","schemaVersion":2},"datasetVersion":"2026-08-28T11:17:15.048Z"}