denoland/deno · error · TypeError

The property 'options.eval' must be false when 'filename' is

Error message

The property 'options.eval' must be false when 'filename' is not a string.

What it means

In eval mode the Worker's first argument is the JavaScript source itself, so it must be a string. When options.eval is truthy and the specifier is not a string (usually a URL object), the constructor throws a plain TypeError: The property 'options.eval' must be false when 'filename' is not a string.

Source

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

    const serializedWorkerMetadata = serializeJsMessageData({
      workerData: options?.workerData,
      environmentData: environmentData,
      env: env_,
      argv: argv_,
      execArgv: options?.execArgv ?? [],
      name: this.#name,
      isEval: !!options?.eval,
      isWorkerThread: true,
      hasStdin: !!options?.stdin,
      resourceLimits: resourceLimits_,
    }, options?.transferList ?? []);

    let sourceCode = "";
    let hasSourceCode = false;

    if (options?.eval) {
      if (typeof specifier !== "string") {
        throw new TypeError(
          "The property 'options.eval' must be false when 'filename' is not a string.",
        );
      }
      const code = specifier;
      // Node.js runs eval workers as CJS (sloppy mode).
      // Pass as source code for execute_script (sloppy mode).
      // `require` is already available from the Node worker bootstrap.
      // See: https://github.com/denoland/deno/issues/26739
      sourceCode = `var __filename = ${
        // deno-lint-ignore deno-internal/prefer-primordials
        JSON.stringify(lazyProcess().default.cwd() + "/[worker eval]")};\n` +
        `var __dirname = ${
          // deno-lint-ignore deno-internal/prefer-primordials
          JSON.stringify(lazyProcess().default.cwd())};\n` +
        `var module = { exports: {} };\n` +
        `var exports = module.exports;\n` +
        code;
      hasSourceCode = true;

View on GitHub (pinned to 9ad36f7a2c)

Solutions

  1. For files, drop the flag: new Worker(url) with eval omitted or false.
  2. For inline code, pass source text: new Worker('console.log(1)', { eval: true }).
  3. Derive the flag from the argument type: { eval: typeof source === 'string' && inline }.

Example fix

// before
new Worker(new URL('./w.js', import.meta.url), { eval: true });

// after
new Worker(new URL('./w.js', import.meta.url));
// eval mode is for source strings:
new Worker("console.log('hi')", { eval: true });
Defensive patterns

Strategy: type-guard

Validate before calling

if (evalMode && typeof spec !== 'string') {
  throw new TypeError('eval mode requires the filename argument to be source code (string)');
}
const w = new Worker(spec, evalMode ? { eval: true } : {});

Type guard

const canEval = (spec: string | URL): spec is string => typeof spec === 'string';

Prevention

When it happens

Trigger: new Worker(new URL('./w.js', import.meta.url), { eval: true }) — a URL/path object combined with eval mode; also new Worker(42, { eval: true }).

Common situations: Refactoring between file-mode and eval-mode workers and leaving eval: true behind; template code that sets eval from a config flag defaulting to true; passing an already-resolved URL where a code string was expected.

Understand the failure class

Background: Invalid argument type errors: "must be of type string", "expected X, got Y", and ERR_INVALID_ARG_TYPE explained — this error's family across 15 libraries.

Related errors


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