ReactiveX/rxjs · error · TypeError

refCount requires a ConnectableObservable

Error message

refCount requires a ConnectableObservable

What it means

The refCount Symbol operator only operates on a ConnectableObservable (the result of publish/publishReplay/multicast). Calling it on a plain Observable throws a TypeError, because refCounting requires the connectable's underlying connection state.

Source

Thrown at packages/rxjs/src/ref-count.ts:23

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

declare global {
  interface Observable<T> {
    [refCount](this: ConnectableObservable<T>): Observable<T>;
  }
}

interface RefCountState {
  activeRuns: number;
  connecting: boolean;
  connection: ConnectableConnection | null;
}

const states = new WeakMap<object, RefCountState>();

Observable.prototype[refCount] = function <T>(this: ConnectableObservable<T>): Observable<T> {
  if (!(this instanceof ConnectableObservable)) {
    throw new TypeError('refCount requires a ConnectableObservable');
  }

  const source = this;

  return Observable[create]<T>((subscriber) => {
    const state = getState(source);
    state.activeRuns++;
    let counted = true;

    subscriber.addTeardown(() => {
      if (!counted) {
        return;
      }
      counted = false;

      state.activeRuns--;
      if (state.activeRuns !== 0) {
        return;

View on GitHub (pinned to 54796b38a5)

Solutions

  1. Apply publish/publishReplay first: source[publishReplay]()[refCount]()
  2. Replace the whole pattern with shareReplay({ bufferSize: n, refCount: true }) which needs no ConnectableObservable
  3. Check instanceof ConnectableObservable before calling refCount in generic code

Example fix

// before
source[refCount]();
// after
source[publishReplay](1)[refCount]();
// or: source[shareReplay]({ bufferSize: 1, refCount: true })
Defensive patterns

Strategy: type-guard

Validate before calling

if (!(source instanceof ConnectableObservable)) {
  source = source[publishReplay](1);
}
source[refCount]();

Type guard

const isConnectable = (o: unknown): o is ConnectableObservable<any> =>
  o instanceof ConnectableObservable;

Prevention

When it happens

Trigger: obs.pipe(shareReplay({refCount: true})) replacement attempts aside — concretely: plainObs[refCount](), or refCount()(plainObs) applied to a non-connectable source; also after refactoring removed the publish step.

Common situations: RxJS 6->7->Next migrations where multicast/publish was dropped but refCount remained in the pipe; applying refCount to the output of operators that return plain Observables.

Related errors


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