ReactiveX/rxjs · error · TypeError

Observable constructor requires a callback

Error message

Observable constructor requires a callback

What it means

The Observable constructor (ObservableImpl) requires a subscriber callback function that receives a Subscriber and sets up the observable's behavior. Passing anything else — undefined, a string, an object, null — throws this TypeError immediately at construction time, matching the platform Observable specification.

Source

Thrown at packages/observable-polyfill/src/index.ts:586

          (output) => {
            subscriber.next(output);
            subscriber.complete();
          },
          (error) => (subscriber as Subscriber<T>)[errorSubscriber](error, false)
        );
      });
    }

    throw new TypeError(`${String(value)} is not observable`);
  }

  #subscriber: WeakRef<Subscriber<T>> | null = null;

  readonly #init: (subscriber: Subscriber<T>) => void;

  constructor(init: (subscriber: Subscriber<T>) => void) {
    if (typeof init !== 'function') {
      throw new TypeError('Observable constructor requires a callback');
    }
    this.#init = init;
  }

  subscribe(observer: Partial<Observer<T>> | ((value: T) => void) | null = {}, options: SubscribeOptions = {}): void {
    if (!canInvokeRealmCallbacks()) {
      return;
    }

    let subscriber = this.#subscriber?.deref();

    const shouldSubscribe = !subscriber?.active;

    if (shouldSubscribe) {
      subscriber = new Subscriber(subscriberToken);
      this.#subscriber = new WeakRef(subscriber);
    }

View on GitHub (pinned to 54796b38a5)

Solutions

  1. Pass a function: new Observable(subscriber => { subscriber.next(value); subscriber.complete(); }).
  2. If you meant to pass an observer, that belongs in subscribe(), not the constructor.
  3. Check the argument is not undefined (broken import or renamed symbol).
  4. Consider a factory helper to centralize construction and validate inputs.

Example fix

// before
new Observable({ next: v => console.log(v) });
// after
new Observable(subscriber => { subscriber.next(1); subscriber.complete(); });
Defensive patterns

Strategy: type-guard

Validate before calling

if (typeof init === 'function') { new Observable(init); } else { new Observable(() => {}); }

Type guard

function isSubscriberCallback(v: unknown): v is (subscriber: any) => void {
  return typeof v === 'function';
}

Try / catch

try { const o = new Observable(init); } catch (e) { if (e instanceof TypeError && /requires a callback/.test(e.message)) { /* supply correct initializer function */ } else throw e; }

Prevention

When it happens

Trigger: new Observable(), new Observable(null), new Observable('handler'), new Observable({ next(...) {} }), or passing a variable that is undefined due to a bad import/typo: new Observable(subscrib).

Common situations: Typos or wrong names in the callback argument; passing an Observer object (next/error/complete) instead of an initializer function — a habit from subscribe(); refactoring where the function was moved and the import broke; default-parameter refactor leaving the argument undefined.

Related errors


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