{"record":{"id":"6e3a830502ceb00c","repo":"shadcn-ui/ui","slug":"usetheme-must-be-used-within-a-themeprovider","errorCode":null,"errorMessage":"useTheme must be used within a ThemeProvider","messagePattern":"useTheme must be used within a ThemeProvider","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"templates/vite-app/src/components/theme-provider.tsx","lineNumber":226,"sourceCode":"    () => ({\n      theme,\n      setTheme,\n    }),\n    [theme, setTheme]\n  )\n\n  return (\n    <ThemeProviderContext.Provider {...props} value={value}>\n      {children}\n    </ThemeProviderContext.Provider>\n  )\n}\n\nexport const useTheme = () => {\n  const context = React.useContext(ThemeProviderContext)\n\n  if (context === undefined) {\n    throw new Error(\"useTheme must be used within a ThemeProvider\")\n  }\n\n  return context\n}\n","sourceCodeStart":208,"sourceCodeEnd":231,"githubUrl":"https://github.com/shadcn-ui/ui/blob/efac5987074af84ece57c367c6dd83387b967022/templates/vite-app/src/components/theme-provider.tsx#L208-L231","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\n<Root />\n// Root.tsx: const { theme } = useTheme() // no ThemeProvider above\n\n// after\n<ThemeProvider defaultTheme=\"dark\" storageKey=\"vite-ui-theme\">\n  <Root />\n</ThemeProvider>","handlingStrategy":"validation","validationCode":"function useOptionalTheme() {\n  const ctx = React.useContext(ThemeProviderContext)\n  return ctx // undefined when no provider\n}\nconst theme = useOptionalTheme()\nif (!theme) return null","typeGuard":"function useHasThemeProvider(): boolean {\n  return React.useContext(ThemeProviderContext) !== undefined\n}","tryCatchPattern":null,"preventionTips":["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."],"tags":["react","context","theme","dark-mode"],"backgroundTag":null,"analyzedSha":"efac5987074af84ece57c367c6dd83387b967022","analyzedAt":"2026-08-12T05:00:50.218Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}