{"record":{"id":"22eb8e097dec2b67","repo":"shadcn-ui/ui","slug":"usesidebar-must-be-used-within-a-sidebarprovider","errorCode":null,"errorMessage":"useSidebar must be used within a SidebarProvider.","messagePattern":"useSidebar must be used within a SidebarProvider\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"apps/v4/registry/bases/aria/ui/sidebar.tsx","lineNumber":53,"sourceCode":"  state: \"expanded\" | \"collapsed\"\n  open: boolean\n  setOpen: (open: boolean) => void\n  openMobile: boolean\n  setOpenMobile: (open: boolean) => void\n  isMobile: boolean\n  toggleSidebar: () => void\n}\n\ntype SidebarButtonProps =\n  | (LinkProps & { href: string })\n  | (ButtonProps & { href?: never })\n\nconst SidebarContext = React.createContext<SidebarContextProps | null>(null)\n\nfunction useSidebar() {\n  const context = React.useContext(SidebarContext)\n  if (!context) {\n    throw new Error(\"useSidebar must be used within a SidebarProvider.\")\n  }\n\n  return context\n}\n\nfunction SidebarProvider({\n  defaultOpen = true,\n  open: openProp,\n  onOpenChange: setOpenProp,\n  className,\n  style,\n  children,\n  ...props\n}: React.ComponentProps<\"div\"> & {\n  defaultOpen?: boolean\n  open?: boolean\n  onOpenChange?: (open: boolean) => void\n}) {","sourceCodeStart":35,"sourceCodeEnd":71,"githubUrl":"https://github.com/shadcn-ui/ui/blob/efac5987074af84ece57c367c6dd83387b967022/apps/v4/registry/bases/aria/ui/sidebar.tsx#L35-L71","documentation":"`useSidebar` reads `SidebarContext` (`createContext<SidebarContextProps | null>(null)`); `<SidebarProvider>` supplies open/openMobile state, setOpen/setOpenMobile, isMobile, toggleSidebar. Any sidebar part (Sidebar/SidebarTrigger/Menu/Inset/etc.) rendered outside `<SidebarProvider>` throws so the open/keyboard state contract holds.","triggerScenarios":"Mounting `<SidebarTrigger />`, `<Sidebar />`, `<SidebarInset />`, or menu items outside `<SidebarProvider>`. Common when the trigger is placed in a top-level header that sits above the provider, or when sidebar markup is split across route segments without a shared provider.","commonSituations":"Reorganizing the app shell so the header (with SidebarTrigger) is no longer under SidebarProvider; SSR rendering order; tests of individual sidebar parts.","solutions":["Wrap the whole app shell (header + sidebar + main) in `<SidebarProvider>` so every sidebar part — including `<SidebarTrigger />` in the header — is a descendant.","If SidebarProvider reads from cookies/localStorage, keep it at the root layout to avoid remounts resetting state.","Decorate tests/stories with `<SidebarProvider>`."],"exampleFix":"// before\n<header>\n  <SidebarTrigger />\n</header>\n<SidebarProvider>\n  <Sidebar />\n</SidebarProvider>\n\n// after\n<SidebarProvider>\n  <header>\n    <SidebarTrigger />\n  </header>\n  <Sidebar />\n</SidebarProvider>","handlingStrategy":"type-guard","validationCode":"render(<SidebarProvider><header><SidebarTrigger/></header><Sidebar/></SidebarProvider>)","typeGuard":"import React from \"react\"\nimport { SidebarContext } from \"@/registry/bases/aria/ui/sidebar\"\nconst insideSidebar = () => React.useContext(SidebarContext) != null","tryCatchPattern":"try { useSidebar() } catch (e) { if (e.message.includes(\"SidebarProvider.\")) {/*wrap shell in SidebarProvider*/} throw e }","preventionTips":["Wrap the whole app shell (header + sidebar + main) in SidebarProvider.","Keep SidebarProvider at the root layout so cookie/localStorage state persists.","Add SidebarProvider to story/test decorators."],"tags":["react","context","hooks","shadcn","sidebar","aria-style"],"backgroundTag":null,"analyzedSha":"efac5987074af84ece57c367c6dd83387b967022","analyzedAt":"2026-08-12T05:00:50.218Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}