janhq/jan · error · Error
DropDrawer components cannot be rendered outside the…
Error message
DropDrawer components cannot be rendered outside the DropDrawer Context
What it means
useDropDrawerContext reads DropDrawerContext created by the DropDrawer root component. DropDrawer sub-items (triggers, content, items) rely on that context for open/close state and mobile behavior; without it the hook throws. It prevents rendering dropdrawer pieces outside the root.
Solutions
- Wrap the dropdrawer sub-components in a <DropDrawer> root component.
- Move the sub-components back inside the DropDrawer JSX tree so context propagates.
- In tests/stories, wrap with a DropDrawer root before rendering items.
- If using React portals, keep the portal created inside the DropDrawer tree (portals still inherit React context).
Example fix
// before
<DropDrawerItem onClick={del}>Delete</DropDrawerItem>
// after
<DropDrawer>
<DropDrawerTrigger>Actions</DropDrawerTrigger>
<DropDrawerContent>
<DropDrawerItem onClick={del}>Delete</DropDrawerItem>
</DropDrawerContent>
</DropDrawer> Defensive patterns
Strategy: type-guard
Validate before calling
const inDropDrawer = () => {
const ctx = React.useContext(DropDrawerContext)
return ctx !== null
} Type guard
const ctx = React.useContext(DropDrawerContext)
if (ctx === null) {
// render fallback or no-op instead of using context values
return null
} Try / catch
try {
renderMenu()
} catch (e) {
if (e instanceof Error && e.message.includes('DropDrawer Context')) {
console.warn('DropDrawer item rendered without root; skipping')
} else throw e
} Prevention
- Keep all DropDrawerItem/Content inside a <DropDrawer> root.
- When portaling content, create the portal inside the DropDrawer tree.
- Add a test rendering each menu composition to catch missing roots early.
When it happens
Trigger: Rendering <DropDrawerItem> or other dropdrawer sub-components without an ancestor <DropDrawer>, e.g. inside a portal, modal, or a list that renders items directly.
Common situations: Placing a DropDrawerItem inside a Tooltip/Popover portal that escapes the React tree context propagation; forgetting the root when refactoring menus; unit tests rendering items alone.
Related errors
- ChainOfThought components must be used within ChainOfThought
- Reasoning components must be used within Reasoning
- Tool components must be used within Tool
- useSidebar must be used within a SidebarProvider.
- Invalid metadata: context_length not found or invalid
AI-assisted analysis of janhq/jan@7205d770c1 (2026-09-17).
Data as JSON: /api/errors/3f99c8d85698e584.
Report an issue: GitHub.
Appendix: source
Thrown at web-app/src/components/ui/dropdrawer.tsx:35
DropdownMenuItem,
DropdownMenuLabel,
DropdownMenuSeparator,
DropdownMenuSub,
DropdownMenuSubContent,
DropdownMenuSubTrigger,
DropdownMenuTrigger,
} from "./dropdown-menu";
import { useIsMobile } from "@/hooks/use-mobile";
import { cn } from "@/lib/utils";
const DropDrawerContext = React.createContext<{ isMobile: boolean }>({
isMobile: false,
});
const useDropDrawerContext = () => {
const context = React.useContext(DropDrawerContext);
if (!context) {
throw new Error(
"DropDrawer components cannot be rendered outside the DropDrawer Context",
);
}
return context;
};
function DropDrawer({
children,
...props
}:
| React.ComponentProps<typeof Drawer>
| React.ComponentProps<typeof DropdownMenu>) {
const isMobile = useIsMobile();
const DropdownComponent = isMobile ? Drawer : DropdownMenu;
return (
<DropDrawerContext.Provider value={{ isMobile }}>
<DropdownComponent
View on GitHub (pinned to 7205d770c1)