denoland/deno · error · ERR_WORKER_PATH

ERR_WORKER_PATH

ERR_WORKER_PATH

Error message

The worker script or module filename must be an absolute path or a relative path starting with './' or '../'.

What it means

String specifiers are treated as filesystem paths, never URLs. If the string starts with 'file://', 'data:', 'http://', or 'https://' and options.eval is not set, the polyfill throws ERR_WORKER_PATH — Node's rule that URL semantics require an actual URL object, so URL strings must be wrapped with new URL(...).

Source

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

    }

    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, "../") &&
        !StringPrototypeStartsWith(path, ".\\") &&
        !StringPrototypeStartsWith(path, "..\\")
      ) {
        // On Windows, also allow drive-letter absolute paths (e.g. C:\...)
        const isWindowsAbsolute = path.length >= 3 && path[1] === ":" &&
          (path[2] === "\\" || path[2] === "/");
        if (!isWindowsAbsolute) {
          throw new ERR_WORKER_PATH(specifier);
        }
      }
    }

View on GitHub (pinned to 9ad36f7a2c)

Solutions

  1. Wrap the string: new Worker(new URL('file:///app/w.js')) or new Worker(new URL('./w.js', import.meta.url)).
  2. For plain local files, drop the scheme and pass '/app/w.js' or './w.js'.
  3. For inline code keep the string but add { eval: true } so it is parsed as source.
  4. Never concatenate import.meta.url as a string; construct a URL object instead.

Example fix

// before
new Worker(import.meta.url + '/w.js'); // string is a file:// URL -> ERR_WORKER_PATH

// after
new Worker(new URL('./w.js', import.meta.url));
Defensive patterns

Strategy: validation

Validate before calling

let spec: string | URL = './w.js';
if (typeof spec === 'string' && /^(file|data|https?):/i.test(spec)) {
  spec = new URL(spec); // URL strings must become URL objects
}
const w = new Worker(spec);

Type guard

const isUrlLikeString = (s: string) => /^(file|data|https?):/i.test(s);

Try / catch

try { const w = new Worker(spec); } catch (e) { if (e?.code === 'ERR_WORKER_PATH' && typeof spec === 'string' && /^(file|data|https?):/i.test(spec)) { const w2 = new Worker(new URL(spec)); } else throw e; }

Prevention

When it happens

Trigger: new Worker('file:///app/w.js'), new Worker('data:text/javascript,...'), or new Worker('https://example.com/w.js') — a URL-scheme-prefixed string without eval mode.

Common situations: String-building specifiers from import.meta.url (which stringifies to a file:// URL); pasting URLs from configs or logs; porting browser worker code that passes URL strings directly.

Related errors


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