{"record":{"id":"8ea5b8bf092576d0","repo":"reduxjs/redux","slug":"expected-the-listener-to-be-a-function-instead-r","errorCode":null,"errorMessage":"Expected the listener to be a function. Instead, received: '${kindOf(listener)}'","messagePattern":"Expected the listener to be a function\\. Instead, received: '(.+?)'","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/createStore.ts","lineNumber":203,"sourceCode":"   *\n   * 1. The subscriptions are snapshotted just before every `dispatch()` call.\n   * If you subscribe or unsubscribe while the listeners are being invoked, this\n   * will not have any effect on the `dispatch()` that is currently in progress.\n   * However, the next `dispatch()` call, whether nested or not, will use a more\n   * recent snapshot of the subscription list.\n   *\n   * 2. The listener should not expect to see all state changes, as the state\n   * might have been updated multiple times during a nested `dispatch()` before\n   * the listener is called. It is, however, guaranteed that all subscribers\n   * registered before the `dispatch()` started will be called with the latest\n   * state by the time it exits.\n   *\n   * @param listener A callback to be invoked on every dispatch.\n   * @returns A function to remove this change listener.\n   */\n  function subscribe(listener: () => void) {\n    if (typeof listener !== 'function') {\n      throw new Error(\n        `Expected the listener to be a function. Instead, received: '${kindOf(\n          listener\n        )}'`\n      )\n    }\n\n    if (isDispatching) {\n      throw new Error(\n        'You may not call store.subscribe() while the reducer is executing. ' +\n          'If you would like to be notified after the store has been updated, subscribe from a ' +\n          'component and invoke store.getState() in the callback to access the latest state. ' +\n          'See https://redux.js.org/api/store#subscribelistener for more details.'\n      )\n    }\n\n    let isSubscribed = true\n\n    ensureCanMutateNextListeners()","sourceCodeStart":185,"sourceCodeEnd":221,"githubUrl":"https://github.com/reduxjs/redux/blob/3084fc33bb23ab4cab4796172eafe342da4e73d9/src/createStore.ts#L185-L221","documentation":"store.subscribe(listener) requires listener to be a function; it is invoked on every dispatch. Passing anything else (undefined, object, string) means there is nothing to call back, so Redux rejects it immediately with a kindOf() report of what was actually passed.","triggerScenarios":"store.subscribe() with no argument; store.subscribe({ next: fn }) (passing an observer object to subscribe instead of the observable interop); store.subscribe(myObj.onChange) without binding `this` losing the function reference; subscribe(null) by accident.","commonSituations":"Confusing store.subscribe(listener) with store[Symbol.observable]().subscribe(observer) — the latter takes an object, the former a function; destructuring a method off an object without binding; passing a React component as the listener; legacy code passing an event-emitter.","solutions":["Pass a plain function: `store.subscribe(() => console.log(store.getState()))`.","If you intended observer-pattern semantics, use the observable interop: `store[Symbol.observable]().subscribe({ next: state => ... })`.","Bind extracted methods: `store.subscribe(myObj.onChange.bind(myObj))`.","Default-check the argument before subscribing: `if (typeof cb === 'function') unsub = store.subscribe(cb)`."],"exampleFix":"// before\nstore.subscribe({ next: () => render() })   // object, not function\n\n// after\nconst unsub = store.subscribe(() => render())\n// or use the observable interop for observer objects:\nstore[Symbol.observable]().subscribe({ next: state => render() })","handlingStrategy":"type-guard","validationCode":"if (typeof listener !== 'function') {\n  throw new TypeError(`listener must be a function, got ${typeof listener}`)\n}\nconst unsub = store.subscribe(listener)","typeGuard":"const isListener = (x): x is () => void => typeof x === 'function'","tryCatchPattern":null,"preventionTips":["Pass a plain function to store.subscribe().","For observer objects, use store[Symbol.observable]().subscribe(observer).","Bind extracted methods before subscribing."],"tags":["redux","createstore","subscribe","listener","type-validation"],"backgroundTag":null,"analyzedSha":"3084fc33bb23ab4cab4796172eafe342da4e73d9","analyzedAt":"2026-08-12T13:21:41.727Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}