{"record":{"id":"a43dae9ce07015fb","repo":"janhq/jan","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":"web-app/src/components/ui/sidebar.tsx","lineNumber":57,"sourceCode":"\tsetOpen: (open: boolean) => void;\n\topenMobile: boolean;\n\tsetOpenMobile: (open: boolean) => void;\n\tisMobile: boolean;\n\ttoggleSidebar: () => void;\n\t//* new properties for sidebar resizing\n\twidth: string;\n\tsetWidth: (width: string) => void;\n\t//* new properties for tracking is dragging rail\n\tisDraggingRail: boolean;\n\tsetIsDraggingRail: (isDraggingRail: boolean) => void;\n};\n\nconst SidebarContext = React.createContext<SidebarContext | null>(null);\n\nfunction useSidebar() {\n\tconst context = React.useContext(SidebarContext);\n\tif (!context) {\n\t\tthrow new Error(\"useSidebar must be used within a SidebarProvider.\");\n\t}\n\n\treturn context;\n}\n\nconst SidebarProvider = React.forwardRef<\n\tHTMLDivElement,\n\tReact.ComponentProps<\"div\"> & {\n\t\tdefaultOpen?: boolean;\n\t\topen?: boolean;\n\t\tonOpenChange?: (open: boolean) => void;\n\t\t//* new prop for default width\n\t\tdefaultWidth?: string;\n\t\t//* new prop for width change callback\n\t\tonWidthChange?: (width: string) => void;\n\t}\n>(\n\t(","sourceCodeStart":39,"sourceCodeEnd":75,"githubUrl":"https://github.com/janhq/jan/blob/7205d770c1e097c3daf35a911176410e93bc5564/web-app/src/components/ui/sidebar.tsx#L39-L75","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\n<Sidebar />\n<SidebarTrigger />\n// after\n<SidebarProvider>\n  <Sidebar />\n  <SidebarTrigger />\n</SidebarProvider>","handlingStrategy":"type-guard","validationCode":"const hasSidebarProvider = () => {\n  const ctx = React.useContext(SidebarContext)\n  return ctx !== null\n}","typeGuard":"const ctx = React.useContext(SidebarContext)\nif (ctx === null) {\n  return null // or render a provider-less fallback layout\n}","tryCatchPattern":"try {\n  renderSidebarLayout()\n} catch (e) {\n  if (e instanceof Error && e.message.includes('SidebarProvider')) {\n    return <SidebarProvider><App/></SidebarProvider>\n  }\n  throw e\n}","preventionTips":["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."],"tags":["react","context"],"backgroundTag":"null-argument","analyzedSha":"7205d770c1e097c3daf35a911176410e93bc5564","analyzedAt":"2026-09-17T14:27:30.100Z","contentChangedAt":"2026-09-17T14:27:30.100Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}