{"record":{"id":"51cc6635576277b5","repo":"reduxjs/redux","slug":"the-slice-reducer-for-key-key-returned-undefi-51cc66","errorCode":null,"errorMessage":"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.","messagePattern":"The slice reducer for key \"(.+?)\" returned undefined when probed with a random type\\. Don't try to handle '(.+?)' 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\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/combineReducers.ts","lineNumber":84,"sourceCode":"    const reducer = reducers[key]\n    const initialState = reducer(undefined, { type: ActionTypes.INIT })\n\n    if (typeof initialState === 'undefined') {\n      throw new Error(\n        `The slice reducer for key \"${key}\" returned undefined during initialization. ` +\n          `If the state passed to the reducer is undefined, you must ` +\n          `explicitly return the initial state. The initial state may ` +\n          `not be undefined. If you don't want to set a value for this reducer, ` +\n          `you can use null instead of undefined.`\n      )\n    }\n\n    if (\n      typeof reducer(undefined, {\n        type: ActionTypes.PROBE_UNKNOWN_ACTION()\n      }) === 'undefined'\n    ) {\n      throw new Error(\n        `The slice reducer for key \"${key}\" returned undefined when probed with a random type. ` +\n          `Don't try to handle '${ActionTypes.INIT}' or other actions in \"redux/*\" ` +\n          `namespace. They are considered private. Instead, you must return the ` +\n          `current state for any unknown actions, unless it is undefined, ` +\n          `in which case you must return the initial state, regardless of the ` +\n          `action type. The initial state may not be undefined, but can be null.`\n      )\n    }\n  })\n}\n\n/**\n * Turns an object whose values are different reducer functions, into a single\n * reducer function. It will call every child reducer, and gather their results\n * into a single state object, whose keys correspond to the keys of the passed\n * reducer functions.\n *\n * @template S Combined state object type.","sourceCodeStart":66,"sourceCodeEnd":102,"githubUrl":"https://github.com/reduxjs/redux/blob/3084fc33bb23ab4cab4796172eafe342da4e73d9/src/combineReducers.ts#L66-L102","documentation":"assertReducerShape also probes each reducer with a random unknown action type (ActionTypes.PROBE_UNKNOWN_ACTION). For any action it does not recognize, the reducer must return the current state (or initial state when current is undefined). Returning undefined for an unknown action signals the reducer swallows unknown actions instead of passing them through, which breaks reducer composition and time-travel.","triggerScenarios":"A reducer that returns undefined for unhandled action types because the switch has no `default: return state`; a reducer that explicitly handles only known actions and falls off the end of the function returning undefined; a reducer that pattern-matches on a closed list of types and forgets the fallback.","commonSituations":"Switch statement missing `default: return state`; reducer authored as `if (action.type === X) return newState` with no else; refactoring that drops the trailing return; TypeScript reducer where exhaustiveness checking tempts authors to omit a default branch.","solutions":["End every reducer's switch with `default: return state` so unknown actions pass through unchanged.","If you use if/else chains, add a final `return state` outside all conditions.","Confirm the reducer never returns undefined for INIT (error 2 fires first if it does) — fix the initial-state default if both errors appear."],"exampleFix":"// before\nfunction counter(state = 0, action) {\n  switch (action.type) {\n    case 'INC': return state + 1\n  }\n}\n\n// after\nfunction counter(state = 0, action) {\n  switch (action.type) {\n    case 'INC': return state + 1\n    default: return state\n  }\n}","handlingStrategy":"validation","validationCode":"// Probe unknown-action behavior of each slice:\nconst probeUnknown = slices => {\n  for (const [key, reducer] of Object.entries(slices)) {\n    const out = reducer(undefined, { type: '@@PROBE_' + Math.random() })\n    if (typeof out === 'undefined') throw new Error(`Slice '${key}' returns undefined for unknown actions`)\n  }\n}\nprobeUnknown({ todos, filter })","typeGuard":"const handlesUnknownAction = reducer =>\n  typeof reducer(undefined, { type: '@@RANDOM_' + Math.random() }) !== 'undefined'","tryCatchPattern":null,"preventionTips":["Always include `default: return state` in reducer switches.","Lint reducers to require a terminal `return state`.","Unit-test each reducer with a random action type and assert a defined, unchanged result."],"tags":["redux","combinereducers","reducer","unknown-action","default-case"],"backgroundTag":null,"analyzedSha":"3084fc33bb23ab4cab4796172eafe342da4e73d9","analyzedAt":"2026-08-12T13:21:41.727Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}