ReactiveX/rxjs · error · Error

list of properties cannot be empty.

Error message

list of properties cannot be empty.

What it means

pluck(...properties) requires at least one property key. Calling the pluck Symbol operator with zero arguments throws, because there is no meaningful 'pluck nothing' projection.

Source

Thrown at packages/rxjs/src/pluck.ts:154

  k1: K1,
  k2: K2,
  k3: K3,
  k4: K4,
  k5: K5,
  k6: K6
): Observable<PluckedValue<PluckedValue<PluckedValue<PluckedValue<PluckedValue<PluckedValue<T, K1>, K2>, K3>, K4>, K5>, K6>>;
function pluckOperator<
  T,
  K1 extends keyof NonNullable<T>,
  K2 extends keyof NonNullable<PluckedValue<T, K1>>,
  K3 extends keyof NonNullable<PluckedValue<PluckedValue<T, K1>, K2>>,
  K4 extends keyof NonNullable<PluckedValue<PluckedValue<PluckedValue<T, K1>, K2>, K3>>,
  K5 extends keyof NonNullable<PluckedValue<PluckedValue<PluckedValue<PluckedValue<T, K1>, K2>, K3>, K4>>,
  K6 extends keyof NonNullable<PluckedValue<PluckedValue<PluckedValue<PluckedValue<PluckedValue<T, K1>, K2>, K3>, K4>, K5>>
>(this: Observable<T>, k1: K1, k2: K2, k3: K3, k4: K4, k5: K5, k6: K6, k7: PluckKey, ...rest: PluckKey[]): Observable<unknown>;
function pluckOperator<T>(this: Observable<T>, ...properties: PluckKey[]): Observable<unknown> {
  if (properties.length === 0) {
    throw new Error('list of properties cannot be empty.');
  }

  return this[map]((value) => {
    let current: unknown = value;

    for (const property of properties) {
      if (current === null || current === undefined) {
        return undefined;
      }
      current = Reflect.get(Object(current), property);
    }

    return current;
  });
}

Observable.prototype[pluck] = pluckOperator;

View on GitHub (pinned to 54796b38a5)

Solutions

  1. Guard before spreading: if (keys.length) obs[pluck](...keys) else obs
  2. Default to identity when no keys: keys.length ? obs[pluck](...keys) : obs
  3. Replace pluck entirely with map(v => v?.a?.b) for static paths (pluck is deprecated in modern RxJS)

Example fix

// before
obs[pluck](...pathSegments); // pathSegments = []
// after
const plucked = pathSegments.length ? obs[pluck](...pathSegments) : obs;
Defensive patterns

Strategy: validation

Validate before calling

if (properties.length === 0) return source; // identity
source[pluck](...properties);

Type guard

const hasKeys = (keys: PluckKey[]) => keys.length > 0;

Prevention

When it happens

Trigger: observable[pluck]() — typically when properties are spread from an empty array: observable[pluck](...keys) with keys.length === 0.

Common situations: Dynamically building a key path from configuration/user input that turns out empty (e.g. path.split('.') on an empty string yields [''], but filter+map steps can yield []), or migration code that forwards optional arguments.

Related errors


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