denoland/deno · error · TypeError
ERR_MODULE_LINK_MISMATCH
ERR_MODULE_LINK_MISMATCH
Error message
Expected ${requests.length} modules, got ${modules.length} What it means
Thrown by SourceTextModule#linkRequests(modules) when the provided array length differs from module.moduleRequests.length (vm.js:793-798). Every static import/exports request in the source must be answered with exactly one module, in the same order as moduleRequests.
Source
Thrown at ext/node/polyfills/vm.js:795
}
get dependencySpecifiers() {
if (this[kDependencySpecifiers] === undefined) {
this[kDependencySpecifiers] = ObjectFreeze(
ArrayPrototypeMap(this[kModuleRequests], (r) => r.specifier),
);
}
return this[kDependencySpecifiers];
}
linkRequests(modules) {
if (this.status !== "unlinked") {
throw new ERR_VM_MODULE_STATUS("must be unlinked");
}
validateArray(modules, "modules");
const requests = this[kModuleRequests];
if (modules.length !== requests.length) {
throw new ERR_MODULE_LINK_MISMATCH(
`Expected ${requests.length} modules, got ${modules.length}`,
);
}
// Validate each provided module first (type + context), then check for
// cache-key collisions: two requests sharing (specifier, attributes)
// must map to the same module instance, matching Node's V8 binding
// behavior. We use this single pass to keep the error precedence
// identical to Node's tests.
const seen = new SafeMap();
const specifiers = [];
const wraps = [];
for (let i = 0; i < modules.length; i++) {
const m = modules[i];
if (!isModule(m)) {
throw new ERR_VM_MODULE_NOT_MODULE();
}
if (m.context !== this[kContext]) {
throw new ERR_VM_MODULE_DIFFERENT_CONTEXT();View on GitHub (pinned to 9ad36f7a2c)
Solutions
- Derive the array from the module itself: `mod.linkRequests(mod.moduleRequests.map(r => resolveModule(r.specifier)))` so lengths always match
- Log `mod.moduleRequests.map(r => r.specifier)` and diff against the modules array before calling
- Regenerate the dependency list whenever sourceText changes; never hardcode the count
- Treat a length mismatch as a bug signal in the bundler/generator, not a runtime condition to catch
Example fix
// before mod.linkRequests([modA]); // source has two imports -> mismatch // after const mods = mod.moduleRequests.map((r) => resolveModule(r.specifier)); mod.linkRequests(mods);
Defensive patterns
Strategy: validation
Validate before calling
const mods = mod.moduleRequests.map((r) => resolve(r.specifier, r.attributes));
if (mods.length !== mod.moduleRequests.length) throw new Error('resolver dropped entries');
mod.linkRequests(mods); Try / catch
try { mod.linkRequests(mods); }
catch (e) {
if (e.code === 'ERR_MODULE_LINK_MISMATCH') {
const want = mod.moduleRequests.map((r) => r.specifier);
throw new Error(`resolved ${mods.length}, source wants ${want.length}: [${want}]`);
} else throw e;
} Prevention
- Derive the modules array from mod.moduleRequests itself rather than a parallel list
- Regenerate dependency arrays whenever the source text changes
- Treat length mismatches as generator bugs: fail loudly, don't catch-and-pad
When it happens
Trigger: Source has two imports (`import 'a'; import 'b'`) but the modules array has one entry; passing modules in a different pipeline that filtered or deduplicated them; hand-writing the array and forgetting a request; a build step generating the module source after the array was computed, adding or removing an import; passing an empty array for a module that does have imports.
Common situations: Plugin loaders where the source text is templated per environment but the dependency array is static; tests that copy a modules array between test cases whose sources differ; caching moduleRequests from an older version of the source; assuming import.meta or dynamic import() entries appear in moduleRequests (only static requests do, which shifts expected counts).
Related errors
- ERR_VM_MODULE_NOT_MODULE
- ERR_VM_MODULE_DIFFERENT_CONTEXT
- ERR_INVALID_ARG_VALUE
- Empty filepath.
- resolve hook must return { shortCircuit: true } or call next
AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20).
Data as JSON: /api/errors/a9b308da0c284530.
Report an issue: GitHub.