ReactiveX/rxjs · error · ArgumentOutOfRangeError

argument out of range

Error message

argument out of range

What it means

elementAt(index) throws ArgumentOutOfRangeError ('argument out of range') immediately when index is negative — a negative index can never match a zero-based emission, so it fails fast at call time rather than erroring per-subscriber. (A separate out-of-range error occurs at completion when no default is supplied.)

Source

Thrown at packages/rxjs/src/element-at.ts:17

import { create } from './create.js';
import { ArgumentOutOfRangeError } from './argument-out-of-range-error.js';
import '@rxjs/observable-polyfill';
import { subscribeToSource } from './util/observable-helpers.js';

export const elementAt: unique symbol = Symbol('elementAt');

declare global {
  interface Observable<T> {
    [elementAt](index: number): Observable<T>;
    [elementAt]<D>(index: number, defaultValue: D): Observable<T | D>;
  }
}

Observable.prototype[elementAt] = function <T, D>(this: Observable<T>, index: number, ...defaultValue: [] | [D]): Observable<T | D> {
  if (index < 0) {
    throw new ArgumentOutOfRangeError();
  }

  const hasDefault = defaultValue.length === 1;
  return this[create]((subscriber) => {
    let count = 0;
    subscribeToSource(this, subscriber, {
      next: (value) => {
        if (count === index) {
          subscriber.next(value);
          subscriber.complete();
          return;
        }
        count++;
      },
      complete: () => {
        if (hasDefault) {
          subscriber.next(defaultValue[0]);
          subscriber.complete();

View on GitHub (pinned to 54796b38a5)

Solutions

  1. Guard the index before calling: Math.max(0, index)
  2. Use first()/last() operators instead of elementAt for those semantics
  3. If the source may be empty, supply a default: elementAt(0, fallback)

Example fix

// before
obs[elementAt](items.length - 1); // -1 when items is empty
// after
obs[elementAt](Math.max(0, items.length - 1), undefined);
Defensive patterns

Strategy: validation

Validate before calling

if (!Number.isInteger(index) || index < 0) throw new RangeError('index must be a non-negative integer');
obs[elementAt](index);

Type guard

const isNonNegativeInt = (n: unknown): n is number => Number.isInteger(n) && (n as number) >= 0;

Prevention

When it happens

Trigger: observable[elementAt](-1), or elementAt(someIndex) where someIndex is computed (e.g. list.length - counter) and goes negative on empty input.

Common situations: Off-by-one bugs with computed indices (length - 1 on an empty collection), porting code that assumed Python-style negative indexing, or clamping logic that never runs before the call.

Related errors


AI-assisted analysis of ReactiveX/rxjs@54796b38a5 (2026-08-28). Data as JSON: /api/errors/2e26238bd3f5edb6. Report an issue: GitHub.