/flags/javascript/node-stack-size
node --stack-size: raise the JavaScript call stack limit (and why it can crash)
- 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
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 defaultThe 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
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
| Setting | What it does |
|---|---|
| --stack-size=N | V8 limit for the JavaScript stack, in KB; no OS change |
| NODE_OPTIONS=--stack-size=N | Rejected: 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=N | Unrelated 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
toJSONthat callsJSON.stringifyon the same object, two functions that call each other without a base case. - Avoid spreading huge arrays into a call:
Math.max(...bigArray)orarr.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
Workerwith a largerstackSizeMb, 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.