shadcn-ui/ui · error · Error
useSidebar must be used within a SidebarProvider.
Error message
useSidebar must be used within a SidebarProvider.
What it means
`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.
Source
Thrown at apps/v4/registry/bases/aria/ui/sidebar.tsx:53
state: "expanded" | "collapsed"
open: boolean
setOpen: (open: boolean) => void
openMobile: boolean
setOpenMobile: (open: boolean) => void
isMobile: boolean
toggleSidebar: () => void
}
type SidebarButtonProps =
| (LinkProps & { href: string })
| (ButtonProps & { href?: never })
const SidebarContext = React.createContext<SidebarContextProps | null>(null)
function useSidebar() {
const context = React.useContext(SidebarContext)
if (!context) {
throw new Error("useSidebar must be used within a SidebarProvider.")
}
return context
}
function SidebarProvider({
defaultOpen = true,
open: openProp,
onOpenChange: setOpenProp,
className,
style,
children,
...props
}: React.ComponentProps<"div"> & {
defaultOpen?: boolean
open?: boolean
onOpenChange?: (open: boolean) => void
}) {View on GitHub (pinned to efac598707)
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>`.
Example fix
// before
<header>
<SidebarTrigger />
</header>
<SidebarProvider>
<Sidebar />
</SidebarProvider>
// after
<SidebarProvider>
<header>
<SidebarTrigger />
</header>
<Sidebar />
</SidebarProvider> Defensive patterns
Strategy: type-guard
Validate before calling
render(<SidebarProvider><header><SidebarTrigger/></header><Sidebar/></SidebarProvider>)
Type guard
import React from "react"
import { SidebarContext } from "@/registry/bases/aria/ui/sidebar"
const insideSidebar = () => React.useContext(SidebarContext) != null Try / catch
try { useSidebar() } catch (e) { if (e.message.includes("SidebarProvider.")) {/*wrap shell in SidebarProvider*/} throw e } Prevention
- 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.
When it happens
Trigger: 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.
Common situations: Reorganizing the app shell so the header (with SidebarTrigger) is no longer under SidebarProvider; SSR rendering order; tests of individual sidebar parts.
Related errors
- useCarousel must be used within a <Carousel />
- useChart must be used within a <ChartContainer />
- useDrawer must be used within a Drawer.
- useProgress must be used within a Progress.
- useSidebar must be used within a SidebarProvider.
AI-assisted analysis of shadcn-ui/ui@efac598707 (2026-08-12).
Data as JSON: /api/errors/22eb8e097dec2b67.
Report an issue: GitHub.