mastra-ai/mastra · error · Error
MainSidebarNavLink accepts either `render` or `asChild`, not
Error message
MainSidebarNavLink accepts either `render` or `asChild`, not both.
What it means
MainSidebarNavLink supports two rendering escape hatches: a `render` element and Radix-style `asChild`. Using both is ambiguous — the component cannot decide which element to clone and style — so it throws immediately during render.
Source
Thrown at packages/playground-ui/src/ds/components/MainSidebar/main-sidebar-nav-link.tsx:73
};
export function MainSidebarNavLink({
link,
state: stateProp,
children,
isActive,
size,
render,
action,
className,
LinkComponent: LinkProp,
level: levelProp,
subItems,
asChild = false,
...props
}: MainSidebarNavLinkProps) {
if (render && asChild) {
throw new Error('MainSidebarNavLink accepts either `render` or `asChild`, not both.');
}
// Auto-inherit state + LinkComponent from context; explicit props still win.
const ctx = useMaybeSidebarState();
const state: SidebarState = stateProp ?? ctx?.state ?? 'default';
const Link: LinkComponent = LinkProp ?? ctx?.LinkComponent ?? 'a';
const isCollapsed = state === 'collapsed';
const isFeatured = link?.variant === 'featured';
const level = levelProp ?? (link?.indent ? 1 : 0);
// A collapsed rail has no room for a trailing control, so the action is dropped there.
const rowAction = isCollapsed ? undefined : action;
const itemClassName = rowAction
? cn(navItemLayoutClasses({ level, size }), 'flex-1 pr-1')
: navItemClasses({ isActive, isCollapsed, isFeatured, level, size });
return (
<li {...props} className={cn('relative flex min-w-0 flex-col', className)}>View on GitHub (pinned to 75dd419e61)
Solutions
- Remove one of the two props: keep `render` if you need custom element rendering with merged className, keep `asChild` if you want the child element cloned with SlottedNavChildProps.
- Audit wrapper components for spread props like {...{render, asChild}} that can both be set.
- Pick a team convention (prefer `render`) and enforce it via lint/props typing (make the union exclusive in TypeScript).
Example fix
// before
<MainSidebarNavLink render={<Link to="/x"/>} asChild href="/x">X</MainSidebarNavLink>
// after
<MainSidebarNavLink render={<Link to="/x"/>} /> Defensive patterns
Strategy: validation
Validate before calling
type NavLinkProps = { render?: React.ReactElement; asChild?: boolean };
function assertNotBoth(props: NavLinkProps) {
if (props.render && props.asChild) {
throw new Error('MainSidebarNavLink accepts either `render` or `asChild`, not both.');
}
}
assertNotBoth(props); // call before rendering Type guard
function usesOnlyRender<P extends { render?: React.ReactElement; asChild?: boolean }>(
props: P,
): props is P & { asChild?: false } {
return !(props.render && props.asChild);
} Try / catch
try {
render(<MainSidebarNavLink render={<Link to="/x"/>} asChild href="/x">X</MainSidebarNavLink>);
} catch (e) {
// strip one prop and retry in dev tooling; fix the call site permanently
} Prevention
- Type the props as an exclusive union (XOR) so both can't be passed at compile time.
- Pick one convention (prefer `render`) across nav call sites.
- Audit wrapper/spread components that may forward both props.
- Add a lint/test that greps for asChild + render co-occurrence on nav links.
When it happens
Trigger: Passing both render={<SomeEl/>} and asChild (with a child element) to MainSidebarNavLink at the same call site; spreading a props object that already contains `render` while also setting asChild.
Common situations: Migrating call sites from asChild to the newer render API and leaving both props; wrapper components that forward their own render prop while also enabling asChild for slotted child props; copy-pasted nav item configs.
Related errors
- MainSidebarNavLink requires a valid React element child when
- traceId and spanId are required
- Trace ID and Span ID are required
- Comment compounds must be rendered within Comment
- ${componentName} must be used within EnvironmentVariablesEdi
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/4a6cccaafb9ae897.
Report an issue: GitHub.