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

  1. Wrap the sidebar layout in <SidebarProvider> at the top of the page/layout component.
  2. Ensure SidebarTrigger/toggle buttons are rendered inside the same provider tree.
  3. In tests, wrap the component under test with SidebarProvider.
  4. 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

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


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)