Skip to content

/flags/javascript/node-stack-size

node --stack-size: raise the JavaScript call stack limit (and why it can crash)

verified onenvironmentlocal · windows 10.0.26200 arm64 · GNU bash 5.3.15 (Git Bash) · v24.20.0updated
tool
JavaScript
command
node
flag
--stack-size=<KB>
default
984 (kilobytes, V8 default reported by node --v8-options)

node --stack-size=N app.js sets how much of the call stack, in kilobytes, V8 lets JavaScript use before it throws RangeError: Maximum call stack size exceeded. A larger value allows deeper recursion. It is a V8 option, not a Node.js one: it only moves V8's limit and does not make the operating system thread stack bigger, so a value above the real stack size crashes the process instead of throwing a catchable error.

Default and effect

bash
node --v8-options | grep -A1 -E '^ +--stack-size '
cat > depth.js <<'EOF'
let depth = 0;
function down() { depth++; down(); }
try { down(); } catch (e) { console.log(e.name + ": " + e.message); }
console.log(depth);
EOF
small=$(node --stack-size=500 depth.js | tail -1)
default=$(node depth.js | tail -1)
large=$(node --stack-size=2000 depth.js | tail -1)
node depth.js | head -1
[ "$small" -lt "$default" ] && echo "--stack-size=500: fewer frames than the default"
[ "$large" -gt "$default" ] && echo "--stack-size=2000: more frames than the default"

Output

  --stack-size (default size of stack region v8 is allowed to use (in kBytes))
        type: int  default: --stack-size=984
RangeError: Maximum call stack size exceeded
--stack-size=500: fewer frames than the default
--stack-size=2000: more frames than the default

The exact depth depends on the size of each frame (local variables, arguments, JIT tier), so the script compares depths instead of printing them. For a small function like this one the depth grows roughly in proportion to the limit; functions with many locals reach the limit sooner.

Above the real stack: a hard crash

bash
node --stack-size=50000 -e 'let d = 0; function f() { d++; f(); } try { f(); } catch (e) { console.log("caught", e.name); }'
echo "exit: $?"

Output

exit: 127

Nothing is printed and the catch never runs: the thread ran off the end of the stack the operating system gave it. The run above is on Windows, where Git Bash reports the status as shown; on Linux the same mistake usually ends with Segmentation fault and status 139. Main-thread stack sizes are set by the OS (often 8 MB on Linux, 1 MB by default for Windows executables, unless the binary requests more), so a value that works on one system can crash on another.

Options at a glance

SettingWhat it does
--stack-size=NV8 limit for the JavaScript stack, in KB; no OS change
NODE_OPTIONS=--stack-size=NRejected: Node.js prints that it is not allowed in NODE_OPTIONS and exits with code 9
ulimit -s (Linux, macOS)Raises the OS stack limit of the shell and the processes it starts
new Worker(file, { resourceLimits: { stackSizeMb } })Per-worker stack size for worker_threads, which Node.js allocates itself
--stack-trace-limit=NUnrelated to depth: number of frames printed in error.stack

Better fixes than a bigger stack

A deeper stack only postpones Maximum call stack size exceeded when the input grows. Prefer:

  • Rewrite the recursion as a loop with an explicit array used as a stack (tree walks, flood fill, parsers).
  • Check for accidental infinite recursion first: a getter that reads itself, a toJSON that calls JSON.stringify on the same object, two functions that call each other without a base case.
  • Avoid spreading huge arrays into a call: Math.max(...bigArray) or arr.push(...other) passes every element as an argument and can overflow the stack with a few hundred thousand items.
  • Move a known-deep computation into a Worker with a larger stackSizeMb, which is supported and portable.

JavaScript engines do not perform tail-call elimination in Node.js, so rewriting a function in tail-recursive form does not help.

Do not confuse the stack with the heap: heap exhaustion is a different error, fixed with --max-old-space-size.

FAQ

Can I put --stack-size in NODE_OPTIONS?

No. Node.js refuses it with the message that --stack-size= is not allowed in NODE_OPTIONS and exits with code 9. Pass it on the command line: node --stack-size=2000 app.js.

What is the default value of --stack-size?

node --v8-options reports default --stack-size=984, in kilobytes, on the Node.js 24 build used for this page. The number is a V8 default, not a Node.js setting, and can change between versions.

Is --stack-size the same as --max-old-space-size?

No. --max-old-space-size limits the heap, where objects live, and fixes heap out of memory errors. --stack-size limits the call stack, where function frames live, and relates to Maximum call stack size exceeded.

Sources