vercel/ai · error

`useUIState` must be used inside an <AI> provider.

Error message

`useUIState` must be used inside an <AI> provider.

What it means

`useUIState` reads the UI state from React context installed by the `<AI>` provider. When the context value is null there is no provider above the component in the tree, so the hook cannot return a state and the SDK throws instead of failing later with an undefined error.

Source

Thrown at packages/rsc/src/shared-client/context.tsx:131

          <InternalSyncUIStateProvider.Provider
            value={clientWrappedSyncUIStateAction}
          >
            {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,
];

View on GitHub (pinned to 69428b1f8b)

Solutions

  1. Render the component inside the `<AI>` provider tree (usually via the root layout that exports the `AI` from `createAI`)
  2. Move the `useUIState` call into a child component that is rendered inside `<AI>`
  3. In tests/stories, wrap the component with the `AI` provider before rendering
  4. Verify with React DevTools that `InternalUIStateProvider` context is non-null at the component

Example fix

// before
export default function Page() {
  const [uiState] = useUIState(); // throws: no provider
  return <Chat />;
}
// after (layout.tsx already renders <AI>)
export default function Page() {
  return <ChatMessages />;
}
function ChatMessages() {
  const [uiState] = useUIState();
  return <div>{uiState.display}</div>;
}
Defensive patterns

Strategy: validation

Validate before calling

// component-level guard before calling the hook in dependent code
function isInsideAIProvider(): boolean {
  return React.useContext(InternalUIStateProvider) != null;
}

Type guard

function hasUIState(
  v: unknown,
): v is [T, (v: T | ((v_: T) => T)) => void] {
  return Array.isArray(v) && v.length === 2;
}

Try / catch

let uiState: T | undefined;
try {
  const [value] = useUIState();
  uiState = value;
} catch (err) {
  if (String(err).includes('must be used inside an <AI> provider')) {
    // render a fallback or rethrow with a clear setup message
    uiState = undefined;
  } else {
    throw err;
  }
}

Prevention

When it happens

Trigger: Calling `useUIState()` in a component rendered without an `<AI>` ancestor — e.g. in a route outside the layout that renders `<AI>`, in a test without the provider, or in a story/portal that escapes the provider tree.

Common situations: Moving a component to a new page whose layout doesn't include `<AI>`; rendering children in a React portal mounted outside the provider; unit tests (Vitest/Jest) rendering the component directly; wrapping only part of the app in `<AI>` and using the hook in the unwrapped part.

Related errors


AI-assisted analysis of vercel/ai@69428b1f8b (2026-08-30). Data as JSON: /api/errors/e194ecd620f37105. Report an issue: GitHub.