Error option limit S1
- Stage: Stage 1
- Status: Active
- ECMAScript edition: —
- Synchronized: Aug 28, 2026
- 中文译文 · Source repository
This proposal introduces a per-error option limit for all built-in Error constructors to control the maximum number of stack frames captured for each error instance. It addresses the problems of the global Error.stackTraceLimit such as coarse granularity, global side effects, and boilerplate workarounds.
The README below comes from the upstream repository and may contain outdated stage or status metadata. Use the proposal details above as the current source of truth.
ECMAScript Proposal: Error option limit
Status
Champion: Ruben Bridgewater
Author: Ruben Bridgewater ruben@bridgewater.de
Stage: 1
Overview
This proposal introduces a new per-error Error options property, limit, that specifies the maximum number of implementation defined stack frames to capture for that specific error instance.
limitis a numeric option interpreted using ToIntegerOrInfinity.- If provided, the local
limitoverrides any global stack trace limit (e.g., V8'sError.stackTraceLimit) for that error only. - Negative values throw a RangeError;
limitmust be a non-negative integer,undefined, orInfinity. - Conceptually, this behaves like temporarily setting the V8 specific
Error.stackTraceLimitimmediately before creating the error and restoring it right after, but without any global side effects.
This provides a standardized, cross-engine way to control stack depth per error instance and avoids manipulating a global knob that affects unrelated errors.
Proposed API
Validation
- If
optionsis provided and has alimitproperty whose value is notundefined, the engine computesn = ToIntegerOrInfinity(limit).- If
n < 0, throw aRangeError. - Otherwise, record
non the error instance.
- If
- If
limitisundefinedor absent, the default behavior is unchanged (the global limit, if any, applies).
Rationale: a local limit is more intuitive
- The global
Error.stackTraceLimitdefined in V8 is coarse-grained and impacts all errors, including those that do not need deeper stacks. - A per-error
limitexpresses intent exactly where it matters and avoids surprising global side effects. - The local limit always overrides the global limit for that specific error instance, which matches developer expectations when tailoring diagnostics.
- Eliminates boilerplate patterns that temporarily modify the global
Error.stackTraceLimitjust to construct one error.
Why the global Error.stackTraceLimit defined in V8 is error-prone
- Changes are process-wide and time-based, so unrelated errors can inherit the wrong limit.
- Code between “set” and “reset” can throw synchronously, skipping the reset.
- Asynchronous boundaries make it easy to affect other in-flight work during
await. - People sometimes simply forget to reset the global knob.
Examples:
- Synchronous throw during error creation skips reset
With a local limit, there’s no global mutation:
- Asynchronous hazard: unrelated errors use your temporary limit
With a local limit, only the intended error is affected:
- Simple omission: forgetting to reset
Per-error limit avoids this entire class of mistakes.
Use cases
- Performance-sensitive hot paths where only the first few frames are needed (e.g.,
limit: 2) to minimize overhead. - Focused deep debugging for specific error types or code paths (e.g.,
limit: 100orInfinity) without changing behavior for other errors. - Library and framework utilities that want predictable stack depth for their own diagnostic errors without affecting user code globally.
In the wild (prior art)
Developers frequently simulate per-error control by temporarily changing the global Error.stackTraceLimit before creating an error and resetting it afterward. Examples and references:
- MDN:
Error.stackTraceLimit(documents temporary adjustment patterns) —https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/stackTraceLimit - Node.js documentation: Errors —
https://nodejs.org/api/errors.html - GitHub code search: “Error.stackTraceLimit = Infinity” —
https://github.com/search?q=%22Error.stackTraceLimit+%3D+Infinity%22&type=code - longjohn (async stack tracing) sets very high/Infinity limits —
https://github.com/mattinsler/longjohn - Mocha full trace option (ecosystem precedent for “full stacks”) —
https://mochajs.org/#--full-trace
These demonstrate that developers already rely on per-error or context-local stack depth control; standardizing a per-error limit removes the need for global mutations.
Semantics
- Let
Lbe the recordedlimitfor the error instance, if provided; otherwiseundefined. - When the host captures the stack for the error:
- If
Lisundefined, apply the host’s default/global stack trace limit. - Otherwise, apply
Las the limit for this error only.
- If
- Formatting and any other host-defined stack processing are unchanged.
A stack frame is implementation defined.
Specification text (outline)
- In each
Error(and subclass) constructor that accepts an options argument:- Let
optionsbe the second (or third, forAggregateError) argument. - If
optionsis notundefined:- Let
limitbe ? Get(options, "limit"). - If
limitis notundefined:- Let
nbe ? ToIntegerOrInfinity(limit). - If
n < 0, throw aRangeError. - Record
non the error instance in an internal slot for later use during stack capture.
- Let
- Let
- Let
- When capturing the stack for an error instance
E:- Let
Sbe the sequence of frames that would be captured forEabsent this option. - Let
nbeE.[[StackTraceLimitOverride]], if present; otherwiseundefined. - Apply the stack length limit:
- If
nisundefined, apply the host’s global/default limit. - Otherwise, apply
ntoS.
- If
- Produce the stack string from
Sas usual.
- Let
See the full spec draft:
Non-goals and edge cases
- This proposal does not standardize stack string formatting, source map application, or async stack joining.
- If
limitis0, no frames are included for the error beyond the error header (implementation defined). - The option is per-error and does not affect other errors or future stack captures.
Alternatives considered
- Continue using global
Error.stackTraceLimit. Rejected for lack of precision, surprising global side effects, and boilerplate required to simulate per-error control. - Add new host-specific APIs. Rejected; standardizing a language option is more portable and interoperable.
Conclusion
limit provides an explicit, local way to control stack depth per error, matching developer expectations, improving ergonomics, and avoiding global side effects while aligning with ecosystem practice.