shadcn-ui/ui · error · Error
useTheme must be used within a ThemeProvider
Error message
useTheme must be used within a ThemeProvider
What it means
useTheme reads ThemeProviderContext. <ThemeProvider> deliberately initializes the context with an explicit undefined default (createContext<... | undefined>(undefined)), so the hook can distinguish 'no provider at all' from 'provider with a real value'. If the context is still undefined at a consumer, there is no <ThemeProvider> ancestor and the hook throws, since dark/light state would otherwise be undefined.
Source
Thrown at templates/vite-app/src/components/theme-provider.tsx:226
() => ({
theme,
setTheme,
}),
[theme, setTheme]
)
return (
<ThemeProviderContext.Provider {...props} value={value}>
{children}
</ThemeProviderContext.Provider>
)
}
export const useTheme = () => {
const context = React.useContext(ThemeProviderContext)
if (context === undefined) {
throw new Error("useTheme must be used within a ThemeProvider")
}
return context
}
View on GitHub (pinned to efac598707)
Solutions
- Wrap the app (or route layout) in <ThemeProvider defaultTheme=... storageKey=...>.
- Ensure the provider is an ancestor of every component calling useTheme.
- For portals/modals, render them within the provider subtree or add a nested provider.
Example fix
// before
<Root />
// Root.tsx: const { theme } = useTheme() // no ThemeProvider above
// after
<ThemeProvider defaultTheme="dark" storageKey="vite-ui-theme">
<Root />
</ThemeProvider> Defensive patterns
Strategy: validation
Validate before calling
function useOptionalTheme() {
const ctx = React.useContext(ThemeProviderContext)
return ctx // undefined when no provider
}
const theme = useOptionalTheme()
if (!theme) return null Type guard
function useHasThemeProvider(): boolean {
return React.useContext(ThemeProviderContext) !== undefined
} Prevention
- Mount <ThemeProvider> at the root (or route layout) so every useTheme consumer is a descendant.
- Render themed portals/modals within the provider subtree or wrap them in their own provider.
- Smoke-test theme-dependent components within <ThemeProvider>.
- Remember this provider uses undefined as its no-provider sentinel — check for undefined, not falsiness, if the value could legitimately be empty.
When it happens
Trigger: Calling useTheme() in a component rendered above/outside <ThemeProvider>; mounting a themed component in a route/layout the provider does not cover; portal content rendered outside the provider subtree.
Common situations: Moving ThemeProvider from the root to a subset of routes; Storybook stories rendering a theme toggle without the provider; refactor that lifts a consumer above the provider.
Related errors
- ${component} must be used within a Questionnaire.Root compon
- ${component} must be used within a Questionnaire.Choice comp
- ${component} must be used within a Questionnaire.Item compon
- usePreviewOverride must be used within a PreviewOverrideProv
- useHistory must be used within HistoryProvider
AI-assisted analysis of shadcn-ui/ui@efac598707 (2026-08-12).
Data as JSON: /api/errors/6e3a830502ceb00c.
Report an issue: GitHub.