microsoft/playwright · error · RangeError

The value of "n" is out of range. It must be a non-negative

Error message

The value of "n" is out of range. It must be a non-negative number. Received ' + n + '.

What it means

Thrown by EventEmitter.setMaxListeners when n is not a non-negative, non-NaN number — a deliberate port of Node's EventEmitter guard. It validates the argument type and range before storing _maxListeners, mirroring Node's RangeError semantics.

Source

Thrown at packages/playwright-core/src/client/eventEmitter.ts:55

  private _events: EventMap | undefined = undefined;
  private _eventsCount = 0;
  private _maxListeners: number | undefined = undefined;
  readonly _pendingHandlers = new Map<EventType, Set<Promise<void>>>();
  private _rejectionHandler: ((error: Error) => void) | undefined;

  constructor() {
    if (this._events === undefined || this._events === Object.getPrototypeOf(this)._events) {
      this._events = Object.create(null);
      this._eventsCount = 0;
    }
    this._maxListeners = this._maxListeners || undefined;
    this.on = this.addListener;
    this.off = this.removeListener;
  }

  setMaxListeners(n: number): this {
    if (typeof n !== 'number' || n < 0 || Number.isNaN(n))
      throw new RangeError('The value of "n" is out of range. It must be a non-negative number. Received ' + n + '.');
    this._maxListeners = n;
    return this;
  }

  getMaxListeners(): number {
    return this._maxListeners === undefined ? NodeEventEmitter.defaultMaxListeners : this._maxListeners;
  }

  emit(type: EventType, ...args: any[]): boolean {
    const events = this._events;
    if (events === undefined)
      return false;

    const handler = events?.[type];
    if (handler === undefined)
      return false;

    if (typeof handler === 'function') {

View on GitHub (pinned to c8fc3bf8d3)

Solutions

  1. Pass a non-negative integer: setMaxListeners(20).
  2. Coerce and validate config-derived values before passing: Number.isFinite(x) && x >= 0 ? x : default.
  3. Pass setMaxListeners(Infinity) only if you truly need unlimited; otherwise use a sane cap.

Example fix

// before
emitter.setMaxListeners(Number(process.env.MAX_LISTENERS)); // NaN when unset

// after
const n = Number(process.env.MAX_LISTENERS);
emitter.setMaxListeners(Number.isFinite(n) && n >= 0 ? n : 10);
Defensive patterns

Strategy: type-guard

Validate before calling

function safeMaxListeners(n, fallback = 10) {
  return typeof n === 'number' && Number.isFinite(n) && n >= 0 ? n : fallback;
}
emitter.setMaxListeners(safeMaxListeners(Number(process.env.MAX_LISTENERS)));

Type guard

function isValidMaxListeners(n: unknown): n is number {
  return typeof n === 'number' && Number.isFinite(n) && n >= 0;
}

Prevention

When it happens

Trigger: Calling setMaxListeners() with a negative number, NaN, a string, undefined, or any non-number value. E.g. page.setMaxListeners(-1), emitter.setMaxListeners('10'), or setMaxListeners(NaN).

Common situations: Reading the limit from env/config without coercing to Number; passing undefined accidentally (forgotten argument); arithmetic that yields NaN; confusing setMaxListeners with a different setter.

Related errors


AI-assisted analysis of microsoft/playwright@c8fc3bf8d3 (2026-08-12). Data as JSON: /api/errors/a4aed7f54dc2b0f0. Report an issue: GitHub.