{"record":{"id":"bc5f63fa267a449e","repo":"vercel/ai","slug":"invalid-state","errorCode":null,"errorMessage":"Invalid state","messagePattern":"Invalid state","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/rsc/src/shared-client/context.tsx","lineNumber":134,"sourceCode":"            {children}\n          </InternalSyncUIStateProvider.Provider>\n        </InternalActionProvider.Provider>\n      </InternalUIStateProvider.Provider>\n    </InternalAIStateProvider.Provider>\n  );\n}\n\nexport function useUIState<AI extends AIProvider = any>() {\n  type T = InferUIState<AI, any>;\n\n  const state = React.useContext<\n    [T, (v: T | ((v_: T) => T)) => void] | null | undefined\n  >(InternalUIStateProvider);\n  if (state === null) {\n    throw new Error('`useUIState` must be used inside an <AI> provider.');\n  }\n  if (!Array.isArray(state)) {\n    throw new Error('Invalid state');\n  }\n  if (state[0] === undefined) {\n    throw new Error(\n      '`initialUIState` must be provided to `createAI` or `<AI>`',\n    );\n  }\n  return state;\n}\n\n// TODO: How do we avoid causing a re-render when the AI state changes but you\n// are only listening to a specific key? We need useSES perhaps?\nfunction useAIState<AI extends AIProvider = any>(): [\n  InferAIState<AI, any>,\n  (newState: ValueOrUpdater<InferAIState<AI, any>>) => void,\n];\nfunction useAIState<AI extends AIProvider = any>(\n  key: keyof InferAIState<AI, any>,\n): [","sourceCodeStart":116,"sourceCodeEnd":152,"githubUrl":"https://github.com/vercel/ai/blob/69428b1f8b037e4d118fb4853428d5c4e620493c/packages/rsc/src/shared-client/context.tsx#L116-L152","documentation":"After confirming the provider exists, `useUIState` validates that the context value is the expected `[state, setState]` tuple. If it is not an array, the provider installed a malformed value, indicating the `InternalUIStateProvider` was provided something other than what `createAI`/`<AI>` supplies.","triggerScenarios":"A custom/mocked `InternalUIStateProvider` value that is not a tuple; intercepting or monkey-patching the context in tests; version skew where a mismatched `ai` package builds the context differently than the one consuming it.","commonSituations":"Test mocks that supply `{ uiState }` objects instead of the `[value, setter]` tuple; duplicate `ai` package copies (different module instances) causing context mismatch after dependency upgrades; manually rendering `InternalAIProvider` with wrong props.","solutions":["Remove any test mock overriding `InternalUIStateProvider` and use the real `AI` provider","Ensure only one version of the `ai` package is installed (`pnpm why ai` / `npm ls ai`) and dedupe","Reinstall node_modules to fix module duplication after upgrades","Render the provider via the component returned by `createAI` instead of constructing context values manually"],"exampleFix":"// before (test mock)\n<InternalUIStateProvider value={{ uiState }}>\n  <MyComponent />\n</InternalUIStateProvider>\n// after\nconst AI = createAI({ ... });\nrender(<AI initialUIState={initialUiState}><MyComponent /></AI>);","handlingStrategy":"type-guard","validationCode":"const ctx = React.useContext(InternalUIStateProvider);\nif (!Array.isArray(ctx)) {\n  throw new Error('InternalUIStateProvider value must be a [state, setState] tuple');\n}","typeGuard":"function isUIStateTuple(v: unknown): v is [unknown, (fn: unknown) => void] {\n  return Array.isArray(v) && v.length === 2 && typeof v[1] === 'function';\n}","tryCatchPattern":"try {\n  const [uiState] = useUIState();\n} catch (err) {\n  if (String(err).includes('Invalid state')) {\n    console.error('Provider context malformed — check for duplicate ai packages or bad test mocks');\n  }\n  throw err;\n}","preventionTips":["Never mock InternalUIStateProvider with a non-tuple value in tests","Keep exactly one version of the ai package installed (npm ls ai / pnpm why ai)","After dependency upgrades, reinstall node_modules and dedupe","Always source the provider from createAI's returned component rather than hand-built context values"],"tags":["react-context","state-shape","duplicate-dependency","rsc"],"backgroundTag":"invalid-state-shape","analyzedSha":"69428b1f8b037e4d118fb4853428d5c4e620493c","analyzedAt":"2026-08-30T12:32:21.016Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}