janhq/jan · error · Error
useSidebar must be used within a SidebarProvider.
Error message
useSidebar must be used within a SidebarProvider.
What it means
useSidebar reads SidebarContext, populated only by SidebarProvider. It exposes state (open/collapsed), mobile detection, and toggle handlers. Rendering any Sidebar family component (Sidebar, SidebarTrigger, SidebarRail, SidebarInset) without the provider yields null context and throws.
Solutions
- Wrap the sidebar layout in <SidebarProvider> at the top of the page/layout component.
- Ensure SidebarTrigger/toggle buttons are rendered inside the same provider tree.
- In tests, wrap the component under test with SidebarProvider.
- If two separate components need the sidebar state, lift the provider to their common ancestor.
Example fix
// before <Sidebar /> <SidebarTrigger /> // after <SidebarProvider> <Sidebar /> <SidebarTrigger /> </SidebarProvider>
Defensive patterns
Strategy: type-guard
Validate before calling
const hasSidebarProvider = () => {
const ctx = React.useContext(SidebarContext)
return ctx !== null
} Type guard
const ctx = React.useContext(SidebarContext)
if (ctx === null) {
return null // or render a provider-less fallback layout
} Try / catch
try {
renderSidebarLayout()
} catch (e) {
if (e instanceof Error && e.message.includes('SidebarProvider')) {
return <SidebarProvider><App/></SidebarProvider>
}
throw e
} Prevention
- Make SidebarProvider the default wrapper in your app/layout shell.
- Wrap sidebar components in route-level layouts, not pages individually.
- Add test setup decorators providing SidebarProvider.
- Lift the provider to a common ancestor if state must be shared across trees.
When it happens
Trigger: Rendering <Sidebar>, <SidebarTrigger>, <SidebarRail> or calling useSidebar() without an ancestor <SidebarProvider>; mounting a sidebar-based layout at a route root where the provider was omitted.
Common situations: Adding a sidebar to a new page/route without copying the provider from existing layouts; test renders of Sidebar components; splitting the layout so the trigger ends up in a sibling tree outside the provider.
Related errors
- ChainOfThought components must be used within ChainOfThought
- DropDrawer components cannot be rendered outside the…
- Reasoning components must be used within Reasoning
- Tool components must be used within Tool
- Invalid metadata: context_length not found or invalid
AI-assisted analysis of janhq/jan@7205d770c1 (2026-09-17).
Data as JSON: /api/errors/a43dae9ce07015fb.
Report an issue: GitHub.
Appendix: source
Thrown at web-app/src/components/ui/sidebar.tsx:57
setOpen: (open: boolean) => void;
openMobile: boolean;
setOpenMobile: (open: boolean) => void;
isMobile: boolean;
toggleSidebar: () => void;
//* new properties for sidebar resizing
width: string;
setWidth: (width: string) => void;
//* new properties for tracking is dragging rail
isDraggingRail: boolean;
setIsDraggingRail: (isDraggingRail: boolean) => void;
};
const SidebarContext = React.createContext<SidebarContext | null>(null);
function useSidebar() {
const context = React.useContext(SidebarContext);
if (!context) {
throw new Error("useSidebar must be used within a SidebarProvider.");
}
return context;
}
const SidebarProvider = React.forwardRef<
HTMLDivElement,
React.ComponentProps<"div"> & {
defaultOpen?: boolean;
open?: boolean;
onOpenChange?: (open: boolean) => void;
//* new prop for default width
defaultWidth?: string;
//* new prop for width change callback
onWidthChange?: (width: string) => void;
}
>(
(View on GitHub (pinned to 7205d770c1)