How a Tiny JSON.parse() Bug Crashed a Node.js Server – Inside the V8 script_list Leak

This article recounts a real‑world incident where a simple JSON.parse() try‑catch block triggered a massive memory leak in a Node.js 12 application, explains how the V8 engine’s script_list retained orphaned script objects, and shows how tools like gdb, llnode and heapdump can be used to locate and fix the issue.

Node Underground
Node Underground
Node Underground
How a Tiny JSON.parse() Bug Crashed a Node.js Server – Inside the V8 script_list Leak

At night on September 15, 2020, an alarm sounded in an office building as a Node.js application began to consume memory explosively, eventually exhausting the system.

try {
    obj = JSON.parse(data);
} catch (err) {
    // ignore
}

The code looks harmless, but it caused a subtle memory leak that traditional heapdump analysis could not reveal; the dump only showed a large, empty “shadow” object consuming hundreds of megabytes.

Investigation with gdb and llnode uncovered that each time JSON.parse() threw an exception, V8 created a script object and added it to v8::script_list. The script objects contain the string "[object Object]" and a few small integer identifiers, but they were never reclaimed because the list’s internal WeakArrayList could not shrink, leaving large gaps.

gdb is used to locate and analyze the C++ implementation of V8/Node. llnode inspects V8 objects in core files, exposing unknown script entries.

The script_list resides in the V8 isolate’s heap. Its address range (e.g., 0x00002090 - 0x056dc5c0) is filled mostly with null pointers, while a LargeObject occupies about 726 MiB, representing the leaked scripts.

Because V8’s pointer compression treats these null slots as live, the garbage collector cannot release them, causing the memory consumption to balloon.

Using gdb breakpoints on the function that pushes scripts onto script_list revealed the call stack triggered during JSON parsing errors, confirming the leak source.

After identifying the problem, the Node.js runtime was upgraded (post‑v12.18.2) where the issue was fixed; earlier 12.x versions are affected, while v10 is not.

All Node.js 12 releases before 12.18.2 suffer from this memory leak.

Node.js v10 is not impacted.

If your application experiences similar memory‑leak symptoms, upgrade to the latest Node.js version or to an Alinode‑patched build.

Node.jsMemory LeakV8GDBheapdumpllnodescript_list
Node Underground
Written by

Node Underground

No language is immortal—Node.js isn’t either—but thoughtful reflection is priceless. This underground community for Node.js enthusiasts was started by Taobao’s Front‑End Team (FED) to share our original insights and viewpoints from working with Node.js. Follow us. BTW, we’re hiring.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.