reduxjs/redux · error · TypeError

Expected the observer to be an object. Instead, received: '$

Error message

Expected the observer to be an object. Instead, received: '${kindOf(observer)}'

What it means

store[Symbol.observable]().subscribe(observer) accepts an observer object (with optional next/error/complete methods). The interop checks typeof observer === 'object' && observer !== null and throws a TypeError otherwise. This is distinct from store.subscribe(listener) which takes a function; passing a function here is a misuse of the observable API.

Source

Thrown at src/createStore.ts:357

   * Interoperability point for observable/reactive libraries.
   * @returns A minimal observable of state changes.
   * For more information, see the observable proposal:
   * https://github.com/tc39/proposal-observable
   */
  function observable() {
    const outerSubscribe = subscribe
    return {
      /**
       * The minimal observable subscription method.
       * @param observer Any object that can be used as an observer.
       * The observer object should have a `next` method.
       * @returns An object with an `unsubscribe` method that can
       * be used to unsubscribe the observable from the store, and prevent further
       * emission of values from the observable.
       */
      subscribe(observer: unknown) {
        if (typeof observer !== 'object' || observer === null) {
          throw new TypeError(
            `Expected the observer to be an object. Instead, received: '${kindOf(
              observer
            )}'`
          )
        }

        function observeState() {
          const observerAsObserver = observer as Observer<S>
          if (observerAsObserver.next) {
            observerAsObserver.next(getState())
          }
        }

        observeState()
        const unsubscribe = outerSubscribe(observeState)
        return { unsubscribe }
      },

View on GitHub (pinned to 3084fc33bb)

Solutions

  1. Pass an observer object: `store[Symbol.observable]().subscribe({ next: state => render() })`.
  2. If you just want a plain callback, use store.subscribe(listener) directly (no Symbol.observable).
  3. When bridging to RxJS, ensure the observer is `{ next, error?, complete? }`, not a bare function.

Example fix

// before
store[Symbol.observable]().subscribe(state => render())   // function, not object -> TypeError

// after
store[Symbol.observable]().subscribe({ next: state => render() })
// or, for a plain callback, skip the observable interop:
store.subscribe(() => render())
Defensive patterns

Strategy: type-guard

Validate before calling

if (observer === null || typeof observer !== 'object') {
  throw new TypeError(`observer must be an object, got ${observer === null ? 'null' : typeof observer}`)
}
store[Symbol.observable]().subscribe(observer)

Type guard

const isObserver = (x): x is { next?: (s:any)=>void; error?: (e:any)=>void; complete?: ()=>void } =>
  x !== null && typeof x === 'object'

Prevention

When it happens

Trigger: store[Symbol.observable]().subscribe(() => render()) — passing a function to the observable subscribe; subscribe(null) or subscribe('cb'); using a subscriber library that hands a callback instead of an observer; RxJS interop where the observer unwrapped to a function.

Common situations: Confusing store.subscribe(fn) with observable.subscribe(observer); adapter code that bridges Redux to RxJS incorrectly; passing an arrow function where an { next } object is expected; migrating from a custom subscribe-API that accepted functions.

Related errors


AI-assisted analysis of reduxjs/redux@3084fc33bb (2026-08-12). Data as JSON: /api/errors/164f4ee41edfac85. Report an issue: GitHub.