reduxjs/redux · error · Error

Dispatching while constructing your middleware is not allowe

Error message

Dispatching while constructing your middleware is not allowed. Other middleware would not be applied to this dispatch.

What it means

applyMiddleware() assigns a temporary dispatch placeholder that throws whenever a middleware invokes store.dispatch while it is still being constructed. During setup the chain has not yet been composed onto the real store.dispatch, so any dispatch fired in that window would silently bypass all other middleware. Redux refuses to run it rather than emit a partial pipeline.

Source

Thrown at src/applyMiddleware.ts:59

  middleware4: Middleware<Ext4, S, any>
): StoreEnhancer<{ dispatch: Ext1 & Ext2 & Ext3 & Ext4 }>
export default function applyMiddleware<Ext1, Ext2, Ext3, Ext4, Ext5, S>(
  middleware1: Middleware<Ext1, S, any>,
  middleware2: Middleware<Ext2, S, any>,
  middleware3: Middleware<Ext3, S, any>,
  middleware4: Middleware<Ext4, S, any>,
  middleware5: Middleware<Ext5, S, any>
): StoreEnhancer<{ dispatch: Ext1 & Ext2 & Ext3 & Ext4 & Ext5 }>
export default function applyMiddleware<Ext, S = any>(
  ...middlewares: Middleware<any, S, any>[]
): StoreEnhancer<{ dispatch: Ext }>
export default function applyMiddleware(
  ...middlewares: Middleware[]
): StoreEnhancer<any> {
  return createStore => (reducer, preloadedState) => {
    const store = createStore(reducer, preloadedState)
    let dispatch: Dispatch = () => {
      throw new Error(
        'Dispatching while constructing your middleware is not allowed. ' +
          'Other middleware would not be applied to this dispatch.'
      )
    }

    const middlewareAPI: MiddlewareAPI = {
      getState: store.getState,
      dispatch: (action, ...args) => dispatch(action, ...args)
    }
    const chain = middlewares.map(middleware => middleware(middlewareAPI))
    dispatch = compose<typeof dispatch>(...chain)(store.dispatch)

    return {
      ...store,
      dispatch
    }
  }
}

View on GitHub (pinned to 3084fc33bb)

Solutions

  1. Move the eager dispatch out of the middleware factory body and into the innermost handler (next => action => { ... }) or a side-effect scheduled after setup (queueMicrotask / a dedicated INIT action dispatched by the app).
  2. If you need an initial action, dispatch it from your application code after createStore(applyMiddleware(...)(...)) returns, not from inside the middleware constructor.
  3. If the dispatch is genuinely meant to run before the store is ready, restructure so the work happens in the next => action => layer where the composed dispatch is available.

Example fix

// before
const myMiddleware = ({ dispatch }) => {
  dispatch({ type: 'MIDDLEWARE_READY' }) // throws: runs during construction
  return next => action => next(action)
}

// after
const myMiddleware = ({ dispatch }) => {
  return next => action => {
    if (action.type === 'APP_INIT') dispatch({ type: 'MIDDLEWARE_READY' })
    return next(action)
  }
}
Defensive patterns

Strategy: validation

Validate before calling

// No dispatch should run during middleware construction.
// Inspect each middleware factory body for calls to `dispatch`/`store.dispatch`
// BEFORE they are wrapped by `next => action => ...`.
const assertNoEagerDispatch = mw => {
  const api = {
    getState: () => ({}),
    dispatch: () => { throw new Error('eager dispatch in middleware factory') }
  }
  mw(api) // triggers outer factory only; inner next=> is returned, not invoked
  return true
}

Type guard

const isMiddleware = x => typeof x === 'function'
// Guard the call site so only well-formed middleware reaches applyMiddleware:
const safeMiddlewares = middlewares.filter(isMiddleware)

Prevention

When it happens

Trigger: A middleware function (the first curried arg handed ({ getState, dispatch }) => next => action => ...) calls middlewareAPI.dispatch(...) synchronously inside its outermost factory body, i.e. during middlewares.map(middleware => middleware(middlewareAPI)) at applyMiddleware.ts:69, before dispatch = compose(...chain)(store.dispatch) has assigned the real dispatch.

Common situations: Middleware that auto-dispatches an init/seed action when instantiated; a logging/analytics middleware that eagerly reports its own startup; migration from redux-thunk where dispatch is called at module top-level while configuring the store; SSR code that dispatches during store assembly.

Related errors


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