{"record":{"id":"6a4d4d638cf3dda4","repo":"streamich/react-use","slug":"state-state-is-not-a-valid-state-does-not-ex","errorCode":null,"errorMessage":"State '${state}' is not a valid state (does not exist in state list)","messagePattern":"State '(.+?)' is not a valid state \\(does not exist in state list\\)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/useStateList.ts","lineNumber":60,"sourceCode":"        if (newIndex === index.current) return;\n\n        // it gives the ability to travel through the left and right borders.\n        // 4ex: if list contains 5 elements, attempt to set index 9 will bring use to 5th element\n        // in case of negative index it will start counting from the right, so -17 will bring us to 4th element\n        index.current =\n          newIndex >= 0\n            ? newIndex % stateSet.length\n            : stateSet.length + (newIndex % stateSet.length);\n        update();\n      },\n      setState: (state: T) => {\n        // do nothing on unmounted component\n        if (!isMounted()) return;\n\n        const newIndex = stateSet.length ? stateSet.indexOf(state) : -1;\n\n        if (newIndex === -1) {\n          throw new Error(`State '${state}' is not a valid state (does not exist in state list)`);\n        }\n\n        index.current = newIndex;\n        update();\n      },\n    }),\n    [stateSet]\n  );\n\n  return {\n    state: stateSet[index.current],\n    currentIndex: index.current,\n    isFirst: index.current === 0,\n    isLast: index.current === stateSet.length - 1,\n    ...actions,\n  };\n}\n","sourceCodeStart":42,"sourceCodeEnd":78,"githubUrl":"https://github.com/streamich/react-use/blob/fbe99c6327e6af94df03bc8bd6ecc5e3ff04fbcc/src/useStateList.ts#L42-L78","documentation":"Thrown by the `setState` function returned from useStateList when the requested state value is not present in the configured state list. Internally setState looks up the index via stateSet.indexOf(state); if it returns -1 (not found), the library refuses to move to a non-existent state and throws. There is an isMounted() guard first, so the throw only occurs while the component is mounted.","triggerScenarios":"Calling controls.setState(someValue) where someValue is not an element of the state list passed to useStateList. Examples: a typo in an enum/union value, a value from a different casing, or an externally-derived value that does not exactly match a list member (also affected by reference equality for object states).","commonSituations":"String/enum mismatches ('Open' vs 'open'); copy-pasting a state machine whose labels differ; object states compared by reference where a fresh object is passed instead of the original list member; deserialized JSON values that do not match the literal list entries.","solutions":["Pass only values that exist in the state list; reference the same constants/literals used to build the list.","Validate membership before calling: if (states.includes(next)) setState(next); else handle the unknown state.","For object states, compare by a stable key/id rather than passing a newly-constructed object, or store the canonical members and reuse references.","Double-check casing/whitespace of string states against the list definition."],"exampleFix":"// before\nconst [state, controls] = useStateList(['open', 'closed', 'pending']);\ncontrols.setState('Open');   // throws: 'open' !== 'Open'\n\n// after\ncontrols.setState('open');\n// or guard:\nif (['open','closed','pending'].includes(next)) controls.setState(next);","handlingStrategy":"validation","validationCode":"const states = ['open', 'closed', 'pending'] as const;\nconst [, controls] = useStateList(states);\n\nfunction safeSetState(next: string) {\n  if (states.includes(next as (typeof states)[number])) {\n    controls.setState(next);\n  } else {\n    console.warn(`Unknown state: ${next}`);\n  }\n}","typeGuard":"const STATES = ['open', 'closed', 'pending'] as const;\ntype State = (typeof STATES)[number];\n\nconst isState = (v: unknown): v is State =>\n  typeof v === 'string' && (STATES as readonly string[]).includes(v);\n\nif (isState(next)) controls.setState(next);\n// else: ignore or log — never call setState with an unknown value","tryCatchPattern":"try {\n  controls.setState(next);\n} catch (e) {\n  // setState is user-triggered (not render), so try/catch is viable here:\n  console.warn(`Rejected state transition to '${next}': not in list`, e);\n}","preventionTips":["Define the state list as a single source of truth (const array / enum) and derive the type from it.","Validate membership with a type guard before calling setState, especially for external/deserialized values.","For object states, compare by a stable id/key rather than a freshly-constructed object.","Watch for casing/whitespace mismatches in string states."],"tags":["react","hooks","state-machine","validation"],"backgroundTag":null,"analyzedSha":"fbe99c6327e6af94df03bc8bd6ecc5e3ff04fbcc","analyzedAt":"2026-08-12T19:24:06.802Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}