reduxjs/redux · error · Error

Actions may not have an undefined "type" property. You may h

Error message

Actions may not have an undefined "type" property. You may have misspelled an action type string constant.

What it means

Even when the action is a plain object, Redux requires a `type` property that is defined. Actions with no type, or with type: undefined, cannot be routed by reducers or recorded by devtools, so dispatch rejects them. This usually indicates a misspelled constant that resolved to undefined.

Source

Thrown at src/createStore.ts:280

   * a `type` property which may not be `undefined`. It is a good idea to use
   * string constants for action types.
   *
   * @returns For convenience, the same action object you dispatched.
   *
   * Note that, if you use a custom middleware, it may wrap `dispatch()` to
   * return something else (for example, a Promise you can await).
   */
  function dispatch(action: A) {
    if (!isPlainObject(action)) {
      throw new Error(
        `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.`
      )
    }

    if (typeof action.type === 'undefined') {
      throw new Error(
        'Actions may not have an undefined "type" property. You may have misspelled an action type string constant.'
      )
    }

    if (typeof action.type !== 'string') {
      throw new Error(
        `Action "type" property must be a string. Instead, the actual type was: '${kindOf(
          action.type
        )}'. Value was: '${String(action.type)}' (stringified)`
      )
    }

    if (isDispatching) {
      throw new Error('Reducers may not dispatch actions.')
    }

    try {
      isDispatching = true

View on GitHub (pinned to 3084fc33bb)

Solutions

  1. Inspect the action object right before dispatch: confirm `action.type` is a defined string.
  2. Check the import for the action-type constant: `import { ADD_TODO } from './types'` and ensure ADD_TODO is exported.
  3. Beware circular imports: move shared constants to a leaf module that no one cycles back from.
  4. Use a linter rule (e.g. eslint-plugin-redux) to flag undefined action types.

Example fix

// before (types.ts exports ADD_TODO, but you imported a typo)
import { ADD_TODO } from './types'        // undefined: not exported
dispatch({ type: ADD_TODO, payload: x })

// after
import { ADD_TODO } from './types'
dispatch({ type: ADD_TODO, payload: x })
Defensive patterns

Strategy: validation

Validate before calling

if (typeof action.type === 'undefined') {
  throw new Error(`Action is missing a defined type: ${JSON.stringify(action)}`)
}
store.dispatch(action)

Type guard

const hasDefinedType = (a): a is { type: unknown } =>
  a !== null && typeof a === 'object' && typeof (a as any).type !== 'undefined'

Prevention

When it happens

Trigger: dispatch({ type: ADD_TODO }) where ADD_TODO is undefined (misspelled or not exported); dispatch({ payload: x }) with no type field at all; action built from a constants object whose key was renamed; reducer/action file using a string literal that got tree-shaken to undefined.

Common situations: Renaming an action-type constant in one file but not the action creator; circular import that makes the constant undefined at dispatch time; copy-paste that omits `type:`; destructuring that yields undefined for the type value.

Related errors


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