denoland/deno · error · TypeError

ERR_INVALID_ARG_TYPE

ERR_INVALID_ARG_TYPE

Error message

The "${name}" argument must be of type function. Received ${actual}

What it means

When compiling sandboxed code that uses dynamic import(), options.importModuleDynamically must be a callback, the sentinel vm.USE_MAIN_CONTEXT_DEFAULT_LOADER, or undefined. validateImportModuleDynamically rejects every other value with ERR_INVALID_ARG_TYPE because the loader has to be callable or that exact well-known constant.

Source

Thrown at ext/node/polyfills/vm.js:216

  createCachedData() {
    return Buffer.from(op_vm_script_create_cached_data(this.#inner));
  }
}

function finishDynamicImportResult(result) {
  if (isModule(result)) {
    return PromisePrototypeThen(result.evaluate(), () => result.namespace);
  }
  return result;
}

function validateImportModuleDynamically(value, name) {
  if (
    value !== undefined &&
    value !== USE_MAIN_CONTEXT_DEFAULT_LOADER &&
    typeof value !== "function"
  ) {
    throw new ERR_INVALID_ARG_TYPE(
      name,
      "function",
      value,
    );
  }
}

function getImportModuleDynamicallyId(value, name, getReferrer) {
  validateImportModuleDynamically(value, name);
  if (value === USE_MAIN_CONTEXT_DEFAULT_LOADER) {
    return -1;
  }
  if (value === undefined) {
    return 0;
  }
  return op_vm_dynamic_import_callback_register(
    (specifier, importAttributes) => {
      return PromisePrototypeThen(

View on GitHub (pinned to 9ad36f7a2c)

Solutions

  1. Pass a function: importModuleDynamically: (specifier, referrer, attributes) => import(specifier).
  2. Or pass the sentinel vm.USE_MAIN_CONTEXT_DEFAULT_LOADER for the default main-context loader.
  3. Omit the option entirely when custom dynamic-import behavior in the sandbox is not needed.

Example fix

// before
new vm.Script(code, { importModuleDynamically: "main" }); // ERR_INVALID_ARG_TYPE

// after
const script = new vm.Script(code, {
  importModuleDynamically: (specifier) => import(specifier),
});
Defensive patterns

Strategy: validation

Validate before calling

import vm from "node:vm";

const isValidImd = (v) =>
  v === undefined ||
  v === vm.USE_MAIN_CONTEXT_DEFAULT_LOADER ||
  typeof v === "function";

const safeImd = isValidImd(opts.importModuleDynamically)
  ? opts.importModuleDynamically
  : undefined;

Type guard

const isValidImportModuleDynamically = (v) =>
  v === undefined ||
  v === vm.USE_MAIN_CONTEXT_DEFAULT_LOADER ||
  typeof v === "function";

Prevention

When it happens

Trigger: new vm.Script(code, { importModuleDynamically: 'main' }), vm.compileFunction(src, [], { importModuleDynamically: {} }), or wiring the option from config/env as a string or boolean.

Common situations: Copying the option into YAML/JSON config where it becomes a string; porting code that targeted an older string-based convention; passing a module namespace object or an import() promise instead of the function itself.

Related errors


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