denoland/deno · error · Error

ERR_VM_MODULE_STATUS

ERR_VM_MODULE_STATUS

Error message

Module status must not be unlinked or linking

What it means

A vm module's namespace object exists only after linking succeeds. Module#namespace reads the module status and throws ERR_VM_MODULE_STATUS('must not be unlinked or linking') while status is below Linked — i.e. before link() runs, or while a link is still in flight.

Source

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

        "vm.SourceTextModule | vm.SyntheticModule",
        this,
      );
    }
    this[kLinkingStatus] = null;
  }

  get identifier() {
    return op_vm_module_get_identifier(this[kWrap]);
  }

  get context() {
    return this[kContext];
  }

  get namespace() {
    const status = op_vm_module_get_status(this[kWrap]);
    if (status < 2) {
      throw new ERR_VM_MODULE_STATUS("must not be unlinked or linking");
    }
    return op_vm_module_get_namespace(this[kWrap]);
  }

  get status() {
    if (this[kLinkingStatus] !== null) {
      return this[kLinkingStatus];
    }
    return STATUS_NAMES[op_vm_module_get_status(this[kWrap])];
  }

  get error() {
    if (this.status !== "errored") {
      throw new ERR_VM_MODULE_STATUS("must be errored");
    }
    return op_vm_module_get_exception(this[kWrap]);
  }

View on GitHub (pinned to 9ad36f7a2c)

Solutions

  1. Await both stages: await m.link(linker); await m.evaluate(); then read m.namespace.
  2. Check m.status before access: only read namespace when status is 'linked' or later.
  3. Chain dependent logic off the evaluate() promise instead of running it in parallel with linking.

Example fix

// before
const m = new vm.SourceTextModule("export const a = 1;");
m.link(linker);
console.log(m.namespace); // ERR_VM_MODULE_STATUS

// after
const m = new vm.SourceTextModule("export const a = 1;");
await m.link(linker);
await m.evaluate();
console.log(m.namespace.a); // 1
Defensive patterns

Strategy: validation

Validate before calling

async function readyModule(m, linker) {
  if (m.status === "unlinked") await m.link(linker);
  if (m.status === "linked") await m.evaluate();
  return m; // .namespace is now safe
}

Try / catch

try {
  use(m.namespace);
} catch (err) {
  if (err.code === "ERR_VM_MODULE_STATUS") {
    throw new Error(`module not ready (status: ${m.status})`, { cause: err });
  }
  throw err;
}

Prevention

When it happens

Trigger: const m = new vm.SourceTextModule(code); m.namespace — or reading namespace without awaiting the promise returned by m.link(linker).

Common situations: Porting vm.Script (CommonJS-style) code where no link phase exists; forgetting ESM-in-vm is asynchronous at two stages (link, then evaluate); callbacks racing the link promise and reading namespace too early.

Related errors


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