denoland/deno · error · ERR_INVALID_URL_SCHEME

ERR_INVALID_URL_SCHEME

ERR_INVALID_URL_SCHEME

Error message

The URL must be one of scheme file or data

What it means

The Worker constructor only accepts URL objects whose protocol is file: or data: — worker code must exist on local disk or be inline. Any other scheme (http:, https:, blob:, ...) throws ERR_INVALID_URL_SCHEME with the allowed list ['file', 'data'], matching Node.js, which never fetches worker scripts over the network.

Source

Thrown at ext/node/polyfills/worker_threads.ts:376

              hasInvalid = true;
              break;
            }
          }
        }
        if (hasInvalid) {
          throw new ERR_WORKER_INVALID_EXEC_ARGV(
            [nodeOptions],
            "invalid NODE_OPTIONS env variable",
          );
        }
      }
    }

    if (typeof specifier === "object") {
      if (
        !(specifier.protocol === "data:" || specifier.protocol === "file:")
      ) {
        throw new ERR_INVALID_URL_SCHEME(["file", "data"]);
      }
    } else if (typeof specifier === "string" && !options?.eval) {
      // Node.js requires string specifiers to be absolute paths or
      // relative paths starting with './' or '../'. URLs passed as
      // strings must be wrapped with `new URL`.
      if (
        StringPrototypeStartsWith(specifier, "file://") ||
        StringPrototypeStartsWith(specifier, "data:") ||
        StringPrototypeStartsWith(specifier, "http://") ||
        StringPrototypeStartsWith(specifier, "https://")
      ) {
        throw new ERR_WORKER_PATH(specifier);
      }
      const path = specifier;
      if (
        !StringPrototypeStartsWith(path, "/") &&
        !StringPrototypeStartsWith(path, "./") &&
        !StringPrototypeStartsWith(path, "../") &&

View on GitHub (pinned to 9ad36f7a2c)

Solutions

  1. Fetch the script in the parent, write it to a temp file, and pass a file URL built with pathToFileURL().
  2. Use a data: URL for small inline scripts: new Worker(new URL('data:text/javascript,' + encodeURIComponent(code))).
  3. For local scripts, resolve relative to the module: new Worker(new URL('./w.js', import.meta.url)).
  4. Never attempt http(s) worker specifiers; materialize the code locally first.

Example fix

// before
const w = new Worker(new URL('https://cdn.example.com/w.js'));

// after
import { pathToFileURL } from 'node:url';
const code = await (await fetch('https://cdn.example.com/w.js')).text();
const tmp = await Deno.makeTempFile({ suffix: '.js' });
await Deno.writeTextFile(tmp, code);
const w = new Worker(pathToFileURL(tmp));
Defensive patterns

Strategy: type-guard

Validate before calling

const spec = new URL(input);
if (spec.protocol !== 'file:' && spec.protocol !== 'data:') {
  throw new Error('worker URL must be file: or data:, got ' + spec.protocol);
}
const w = new Worker(spec);

Type guard

function isWorkerUrl(u: unknown): u is URL {
  return u instanceof URL && (u.protocol === 'file:' || u.protocol === 'data:');
}

Try / catch

try { const w = new Worker(url); } catch (e) { if (e?.code === 'ERR_INVALID_URL_SCHEME') { /* download/bundle the script locally and switch to a file: URL */ } else throw e; }

Prevention

When it happens

Trigger: new Worker(new URL('https://example.com/w.mjs')) or new Worker(new URL('blob:...')) — any URL object whose .protocol is not 'file:' or 'data:'.

Common situations: Porting browser code that uses URL.createObjectURL(blob) for inline workers; pointing at CDN-hosted worker scripts; config systems that hand out http(s) URLs where a local module path was expected.

Related errors


AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20). Data as JSON: /api/errors/167f94fe573b2152. Report an issue: GitHub.