GitbookIO/gitbook · error · Error
useAIChatController must be used within an AIChatProvider
Error message
useAIChatController must be used within an AIChatProvider
What it means
Thrown by useAIChatController(), which reads an AIChatController from the AIChatControllerContext React context. If no ancestor rendered the component that supplies the controller (the AIChatProvider-equivalent), useContext returns null and the hook throws, mirroring the standard React 'used outside provider' pattern.
Source
Thrown at packages/gitbook/src/components/AI/useAIChat.tsx:841
onCancelQueuedMessage,
onEvent,
]);
return (
<AIChatControllerContext.Provider value={controller}>
{children}
</AIChatControllerContext.Provider>
);
}
/**
* Get the controller to interact with the AI chat.
* Integrates with search state to synchronize ?ask= parameter.
*/
export function useAIChatController(): AIChatController {
const controller = React.useContext(AIChatControllerContext);
if (!controller) {
throw new Error('useAIChatController must be used within an AIChatProvider');
}
return controller;
}
export function getAIChatStatus(chat: AIChatState): AIChatStatus {
if (chat.error) {
return 'error';
}
if (chat.control) {
return 'confirm';
}
if (chat.responding) {
const latestMessage = getLatestAssistantMessage(chat.messages);
const phase = latestMessage?.activity?.currentPhase;
switch (phase) {
case AIMessageStepPhase.Commentary:View on GitHub (pinned to db67585ee2)
Solutions
- Move the consuming component inside the component tree that provides AIChatControllerContext (the shipped AI chat root component).
- Alternatively, create the controller yourself with the underlying hook that builds it and pass it via your own provider/context.
- In tests/Storybook, wrap the consumer in the provider or a fixture that supplies a stub controller.
- Audit the component tree (React DevTools) to confirm the provider is an ancestor of every useAIChatController call site.
Example fix
// before
export function ChatInputBar() {
const controller = useAIChatController(); // throws: rendered outside chat tree
}
// after
// place ChatInputBar inside the chat provider subtree:
<AIChat>
<ChatInputBar /> {/* now a descendant of AIChatControllerContext.Provider */}
</AIChat> Defensive patterns
Strategy: type-guard
Validate before calling
// Structurally guarantee the consumer is inside the chat provider tree:
<AIChat>
<CustomChatInput /> {/* useAIChatController is safe here */}
</AIChat> Type guard
function useOptionalAIChatController(): AIChatController | null {
return React.useContext(AIChatControllerContext);
}
// then:
const controller = useOptionalAIChatController();
if (!controller) return null; Prevention
- Use a nullable useContext wrapper when a component may mount outside the chat tree.
- Keep custom chat chrome (input bars, footers) as children of the chat root component.
- Add a render-time assertion in dev builds that the provider exists.
When it happens
Trigger: Calling useAIChatController() in a component not descended from the chat provider that sets AIChatControllerContext; using the controller hook in a header/prompt bar component that lives outside the chat subtree; rendering in isolation (Storybook/tests) without the provider wrapper; accessing the controller during SSR before the provider mounted is not the issue — it is purely tree structure.
Common situations: Building custom chat UI pieces (input bars, suggestion chips) placed outside the shipped chat component tree; refactoring that moved the consumer above the provider; test renders without the provider wrapper.
Related errors
- useAI must be used within AIContextProvider
- This component must be used within a <GitBookProvider />
- GitBook client not initialized. Call GitBook("init", { siteU
- No response found
- The AI Assistant is not enabled for this site.
AI-assisted analysis of GitbookIO/gitbook@db67585ee2 (2026-08-28).
Data as JSON: /api/errors/c29cb98d0edf429a.
Report an issue: GitHub.