Skip to content

v24: discarded vm contexts cause OOM; possible V8 backport #66053

Description

@domenic

Version

v24.21.0

Platform

Linux x86_64, kernel 6.8.0-139-generic

Subsystem

vm, V8

What steps will reproduce the bug?

Save as repro.mjs; run node --max-old-space-size=128 repro.mjs.

import { runInNewContext } from "node:vm";
import { setImmediate } from "node:timers/promises";

const source = `
  globalThis.payload = new Array(1_000_000).fill(0);
  ${Array.from({ length: 30 }, (_, index) => `
    function work${index}(values) {
      let result = 0;
      for (let i = 0; i < values.length; ++i) {
        result += Math.sqrt(values[i] * values[i] + ${index});
      }
      return result;
    }
  `).join("\n")}
  const values = [1, 2, 3, 4, 5];
  for (let i = 0; i < 1000; ++i) {
    ${Array.from({ length: 30 }, (_, index) => `work${index}(values);`).join("\n")}
  }
`;

for (let i = 0; i < 100; ++i) {
  runInNewContext(source + `\n// ${i}`);
  await setImmediate();
}
console.log("Completed");

How often does it reproduce? Is there a required condition?

Repeatedly on v24.15.0, v24.16.0, and v24.21.0. Completes on v22.23.2, v26.8.2, or with --no-concurrent-recompilation on v24.

What is the expected behavior? Why is that the expected behavior?

Print Completed; discarded contexts should be collectible.

What do you see instead?

FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory

Additional information

This surfaced in jsdom’s WPT runner with the default ~4 GB heap; the smaller limit makes this reproduction quick. Sampled heap retainers point through V8’s IdentityMapBase to realm prototypes, keeping entire windows alive.

Could V8’s “Stop collecting array and object prototypes” change be backported to v24? Its later thread-safety follow-up might also be relevant.

I haven't verified that those commits are the key ones, but it's worth trying.

Activity

  1. inoway46 commented on Sep 16, 2026

    @inoway46
    Contributor

    Reproduced with official Linux x64 binaries using the same script and --max-old-space-size=128:

    Version Default --no-concurrent-recompilation
    v22.23.2 10/10 completed 3/3 completed
    v24.21.0 10/10 OOM 3/3 completed
    v26.8.2 10/10 completed 3/3 completed

    All v24 default runs exited with SIGABRT:

    FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory
    
  2. added
    confirmed-bugIssues and PRs for confirmed bugs.
    vmIssues and PRs related to the vm subsystem.
    v8 engineIssues and PRs related to the V8 dependency.
    v24.xIssues that can be reproduced on v24.x or PRs targeting the v24.x-staging branch.
    on Sep 16, 2026
  3. inoway46 commented on Sep 17, 2026

    @inoway46
    Contributor

    I confirmed that backporting the relevant V8 changes fixes the repro on v24.21.0:

    https://github.com/inoway46/node/actions/runs/35083804474

    I’m preparing a backport PR now and should have it up later.

  4. added a commit that references this issue on Oct 10, 2026
  5. inoway46 commented on Oct 11, 2026

    @inoway46
    Contributor

    Fixed by #66089, which has landed on v24.x-staging. The fix will be included in a future v24.x release.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    confirmed-bugIssues and PRs for confirmed bugs.v24.xIssues that can be reproduced on v24.x or PRs targeting the v24.x-staging branch.v8 engineIssues and PRs related to the V8 dependency.vmIssues and PRs related to the vm subsystem.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions