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
- Pass a function: importModuleDynamically: (specifier, referrer, attributes) => import(specifier).
- Or pass the sentinel vm.USE_MAIN_CONTEXT_DEFAULT_LOADER for the default main-context loader.
- 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
- Keep loader configuration in code, not in serialized config files.
- The sentinel is a unique constant value — never its string name.
- vm.compileFunction accepts the same option; validate once in a shared helper.
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
- ERR_INVALID_ARG_TYPE
- ERR_INVALID_ARG_TYPE
- ERR_VM_MODULE_STATUS
- ERR_VM_MODULE_ALREADY_LINKED
- ERR_VM_MODULE_NOT_MODULE
AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20).
Data as JSON: /api/errors/2488ab93d498ada1.
Report an issue: GitHub.