vercel/ai · error
Invalid state
Error message
Invalid state
What it means
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.
Source
Thrown at packages/rsc/src/shared-client/context.tsx:134
{children}
</InternalSyncUIStateProvider.Provider>
</InternalActionProvider.Provider>
</InternalUIStateProvider.Provider>
</InternalAIStateProvider.Provider>
);
}
export function useUIState<AI extends AIProvider = any>() {
type T = InferUIState<AI, any>;
const state = React.useContext<
[T, (v: T | ((v_: T) => T)) => void] | null | undefined
>(InternalUIStateProvider);
if (state === null) {
throw new Error('`useUIState` must be used inside an <AI> provider.');
}
if (!Array.isArray(state)) {
throw new Error('Invalid state');
}
if (state[0] === undefined) {
throw new Error(
'`initialUIState` must be provided to `createAI` or `<AI>`',
);
}
return state;
}
// TODO: How do we avoid causing a re-render when the AI state changes but you
// are only listening to a specific key? We need useSES perhaps?
function useAIState<AI extends AIProvider = any>(): [
InferAIState<AI, any>,
(newState: ValueOrUpdater<InferAIState<AI, any>>) => void,
];
function useAIState<AI extends AIProvider = any>(
key: keyof InferAIState<AI, any>,
): [View on GitHub (pinned to 69428b1f8b)
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
Example fix
// before (test mock)
<InternalUIStateProvider value={{ uiState }}>
<MyComponent />
</InternalUIStateProvider>
// after
const AI = createAI({ ... });
render(<AI initialUIState={initialUiState}><MyComponent /></AI>); Defensive patterns
Strategy: type-guard
Validate before calling
const ctx = React.useContext(InternalUIStateProvider);
if (!Array.isArray(ctx)) {
throw new Error('InternalUIStateProvider value must be a [state, setState] tuple');
} Type guard
function isUIStateTuple(v: unknown): v is [unknown, (fn: unknown) => void] {
return Array.isArray(v) && v.length === 2 && typeof v[1] === 'function';
} Try / catch
try {
const [uiState] = useUIState();
} catch (err) {
if (String(err).includes('Invalid state')) {
console.error('Provider context malformed — check for duplicate ai packages or bad test mocks');
}
throw err;
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- You can't get the "${String(key)}" field from the AI state b
- You can't modify the "${String(key)}" field of the AI state
- `useUIState` must be used inside an <AI> provider.
- ${method}: Value stream is already closed.
- ${method}: Value stream is locked and cannot be updated.
AI-assisted analysis of vercel/ai@69428b1f8b (2026-08-30).
Data as JSON: /api/errors/bc5f63fa267a449e.
Report an issue: GitHub.