{"record":{"id":"4a6cccaafb9ae897","repo":"mastra-ai/mastra","slug":"mainsidebarnavlink-accepts-either-render-or-asc","errorCode":null,"errorMessage":"MainSidebarNavLink accepts either `render` or `asChild`, not both.","messagePattern":"MainSidebarNavLink accepts either `render` or `asChild`, not both\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/playground-ui/src/ds/components/MainSidebar/main-sidebar-nav-link.tsx","lineNumber":73,"sourceCode":"};\n\nexport function MainSidebarNavLink({\n  link,\n  state: stateProp,\n  children,\n  isActive,\n  size,\n  render,\n  action,\n  className,\n  LinkComponent: LinkProp,\n  level: levelProp,\n  subItems,\n  asChild = false,\n  ...props\n}: MainSidebarNavLinkProps) {\n  if (render && asChild) {\n    throw new Error('MainSidebarNavLink accepts either `render` or `asChild`, not both.');\n  }\n\n  // Auto-inherit state + LinkComponent from context; explicit props still win.\n  const ctx = useMaybeSidebarState();\n  const state: SidebarState = stateProp ?? ctx?.state ?? 'default';\n  const Link: LinkComponent = LinkProp ?? ctx?.LinkComponent ?? 'a';\n  const isCollapsed = state === 'collapsed';\n  const isFeatured = link?.variant === 'featured';\n  const level = levelProp ?? (link?.indent ? 1 : 0);\n  // A collapsed rail has no room for a trailing control, so the action is dropped there.\n  const rowAction = isCollapsed ? undefined : action;\n\n  const itemClassName = rowAction\n    ? cn(navItemLayoutClasses({ level, size }), 'flex-1 pr-1')\n    : navItemClasses({ isActive, isCollapsed, isFeatured, level, size });\n\n  return (\n    <li {...props} className={cn('relative flex min-w-0 flex-col', className)}>","sourceCodeStart":55,"sourceCodeEnd":91,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/playground-ui/src/ds/components/MainSidebar/main-sidebar-nav-link.tsx#L55-L91","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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)."],"exampleFix":"// before\n<MainSidebarNavLink render={<Link to=\"/x\"/>} asChild href=\"/x\">X</MainSidebarNavLink>\n// after\n<MainSidebarNavLink render={<Link to=\"/x\"/>} />","handlingStrategy":"validation","validationCode":"type NavLinkProps = { render?: React.ReactElement; asChild?: boolean };\nfunction assertNotBoth(props: NavLinkProps) {\n  if (props.render && props.asChild) {\n    throw new Error('MainSidebarNavLink accepts either `render` or `asChild`, not both.');\n  }\n}\nassertNotBoth(props); // call before rendering","typeGuard":"function usesOnlyRender<P extends { render?: React.ReactElement; asChild?: boolean }>(\n  props: P,\n): props is P & { asChild?: false } {\n  return !(props.render && props.asChild);\n}","tryCatchPattern":"try {\n  render(<MainSidebarNavLink render={<Link to=\"/x\"/>} asChild href=\"/x\">X</MainSidebarNavLink>);\n} catch (e) {\n  // strip one prop and retry in dev tooling; fix the call site permanently\n}","preventionTips":["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."],"tags":["react","props-validation","api-misuse","playground-ui"],"backgroundTag":"conflicting-props","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T08:17:16.595Z"}