Redux Error Messages for Invalid Store Configuration: Complete Reference
Redux throws descriptive, actionable error messages when you pass invalid arguments to createStore, combineReducers, bindActionCreators, or applyMiddleware, helping you identify whether the issue is a non-function reducer, malformed actions, or improper enhancer composition.
When configuring a Redux store in the reduxjs/redux library, validation logic runs immediately to ensure your setup follows Redux architectural constraints. If you provide an invalid reducer, dispatch malformed actions, or misuse store enhancers, Redux throws specific errors with detailed explanations and often includes links to documentation. This reference documents every validation error thrown during store configuration, citing exact file paths and line numbers from the source code.
createStore Validation Errors
The createStore function in src/createStore.ts performs extensive validation on its arguments and runtime behavior.
Invalid Reducer Function
If the reducer argument is not a function, Redux throws:
Expected the root reducer to be a function. Instead, received: '${kindOf(reducer)}'
This check occurs at src/createStore.ts L108‑L112.
Multiple Store Enhancers
When you pass more than two arguments to createStore (indicating multiple enhancers), Redux rejects this with:
It looks like you are passing several store enhancers to createStore(). This is not supported. Instead, compose them together to a single function. See https://redux.js.org/tutorials/fundamentals/part-4-store#creating-a-store-with-enhancers for an example.
This validation is located at src/createStore.ts L119‑L124.
Invalid Enhancer Type
If the enhancer argument is provided but is not a function:
Expected the enhancer to be a function. Instead, received: '${kindOf(enhancer)}'
Found at src/createStore.ts L133‑L137.
Subscription Listener Errors
The subscribe method validates listeners and dispatch state.
Non-function listener:
Expected the listener to be a function. Instead, received: '${kindOf(listener)}'
Source: src/createStore.ts L212‑L216.
Subscribing during dispatch:
You may not call store.subscribe() while the reducer is executing. If you would like to be notified after the store has been updated, subscribe from a component and invoke store.getState() in the callback to access the latest state. See https://redux.js.org/api/store#subscribelistener for more details.
Source: src/createStore.ts L220‑L226.
Unsubscribing during dispatch:
You may not unsubscribe from a store listener while the reducer is executing. See https://redux.js.org/api/store#subscribelistener for more details.
Source: src/createStore.ts L240‑L246.
Dispatch Action Validation
The dispatch method enforces strict rules on action objects.
Non-plain-object action:
Actions must be plain objects. Instead, the actual type was: '${kindOf(action)}'. You may need to add middleware to your store setup to handle dispatching other values, such as 'redux-thunk' to handle dispatching functions. See https://redux.js.org/tutorials/fundamentals/part-4-store#middleware and https://redux.js.org/tutorials/fundamentals/part-6-async-logic#using-the-redux-thunk-middleware for examples.
Source: src/createStore.ts L281‑L286.
Missing type property:
Actions may not have an undefined "type" property. You may have misspelled an action type string constant.
Source: src/createStore.ts L289‑L293.
Non-string type property:
Action "type" property must be a string. Instead, the actual type was: '${kindOf(action.type)}'. Value was: '${action.type}' (stringified)
Source: src/createStore.ts L295‑L301.
Recursive dispatch attempt:
Reducers may not dispatch actions.
Source: src/createStore.ts L303‑L306.
replaceReducer Validation
When calling store.replaceReducer(), the new reducer must be a function:
Expected the nextReducer to be a function. Instead, received: '${kindOf(nextReducer)}'
Source: src/createStore.ts L330‑L334.
Observable Validation
If using the observable interop, the observer must be an object:
Expected the observer to be an object. Instead, received: '${kindOf(observer)}'
Source: src/createStore.ts L664‑L670.
combineReducers Validation Errors
The combineReducers utility in src/combineReducers.ts validates the shape and behavior of slice reducers.
Undefined State on Initialization
If a slice reducer returns undefined during the initial @@INIT action:
The slice reducer for key "${key}" returned undefined during initialization. If the state passed to the reducer is undefined, you must explicitly return the initial state. The initial state may not be undefined. If you don't want to set a value for this reducer, you can use null instead of undefined.
Source: src/combineReducers.ts L69‑L76.
Undefined State on Unknown Actions
When probed with a random action type to verify proper default case handling:
The slice reducer for key "${key}" returned undefined when probed with a random type. Don't try to handle '${ActionTypes.INIT}' or other actions in "redux/*" namespace. They are considered private. Instead, you must return the current state for any unknown actions, unless it is undefined, in which case you must return the initial state, regardless of the action type. The initial state may not be undefined, but can be null.
Source: src/combineReducers.ts L80‑L92.
Undefined State on Handled Actions
If a slice reducer explicitly handles an action type but returns undefined:
When called with an action of type ${actionType ? `"${String(actionType)}"` : '(unknown type)'}, the slice reducer for key "${key}" returned undefined. To ignore an action, you must explicitly return the previous state. If you want this reducer to hold no value, you can return null instead of undefined.
Source: src/combineReducers.ts L84‑L92.
bindActionCreators Validation Errors
The bindActionCreators utility in src/bindActionCreators.ts validates its input.
Wrong Argument Type
If actionCreators is neither a function nor a plain object:
bindActionCreators expected an object or a function, but instead received: '${kindOf(actionCreators)}'. Did you write "import ActionCreators from" instead of "import * as ActionCreators from"?
Source: src/bindActionCreators.ts L66‑L73.
applyMiddleware Validation Errors
The applyMiddleware function in src/applyMiddleware.ts prevents improper usage during initialization.
Dispatching During Middleware Construction
If middleware attempts to dispatch an action while being constructed:
Dispatching while constructing your middleware is not allowed. Other middleware would not be applied to this dispatch.
Source: src/applyMiddleware.ts L58‑L63.
Summary
- Redux validates all store configuration arguments immediately in
createStore, throwing descriptive errors for non-function reducers, invalid enhancers, and malformed actions. - Action dispatching is strictly policed: actions must be plain objects with string
typeproperties, and reducers cannot dispatch recursively. - Subscription lifecycle is protected: you cannot subscribe or unsubscribe while a reducer is executing.
- Slice reducers must never return undefined during initialization or for unknown actions, though
nullis acceptable as an explicit empty value. - Middleware construction is atomic: dispatching during middleware setup is prohibited to ensure proper middleware chain formation.
Frequently Asked Questions
What happens if I pass a non-function as the reducer to createStore?
Redux throws Expected the root reducer to be a function. Instead, received: '${kindOf(reducer)}' immediately when calling createStore. This check occurs at line 108 of src/createStore.ts before any state initialization happens.
Why does Redux throw an error when I return undefined from a reducer?
Returning undefined from a slice reducer signals potential logic errors, as Redux uses undefined to detect uninitialized state. The library throws messages like The slice reducer for key "${key}" returned undefined during initialization to force explicit initial state returns or the use of null for empty values.
Can I dispatch an action inside my reducer?
No. Redux explicitly forbids this with the error Reducers may not dispatch actions. at line 303 of src/createStore.ts. This architectural constraint ensures reducers remain pure functions without side effects that could trigger cascading updates.
What should I do if I see the error about passing several store enhancers?
You must compose multiple enhancers into a single function using compose. The error message at line 119 of src/createStore.ts explicitly directs you to the Redux documentation for examples on how to combine enhancers like Redux DevTools and middleware into one composed enhancer function.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →