Popover: PopoverContent throws "Primitive.div failed to slot onto its children" on mount (React 19)
Bug report
Current Behavior
PopoverContent throws immediately on mount:
Error: Primitive.div failed to slot onto its children. Expected a single React element child or `Slottable`.
at Primitive.div.Slot
at updateForwardRef
at beginWork
...This happens with a minimal, standard usage — a single valid-element child, no fragments, no arrays, nothing unusual:
import { Popover, PopoverContent, PopoverTrigger } from "radix-ui" // (also reproduces via the standalone @radix-ui/react-popover package)
function Demo() {
return (
<Popover.Root>
<Popover.Trigger asChild>
<button type="button">Open popover</button>
</Popover.Trigger>
<Popover.Portal>
<Popover.Content>
<div>Hello</div>
</Popover.Content>
</Popover.Portal>
</Popover.Root>
)
}Clicking the trigger throws the error above the moment Popover.Content mounts. The trigger itself renders fine before that — the crash is specifically on Content mount, not on Trigger/Anchor composition.
Expected behavior
The popover opens and renders its content, same as Tooltip and Dialog do with an equivalent structure.
Reproduction / isolation notes
I spent a while isolating this before filing, since I initially assumed it was a mistake in my own code:
- Reproduces with a single child — not a multiple-children-into-
Slotissue (ruled out theSlottablescenario from #3747, which is a different pattern). - Reproduces with
modalbothtrueandfalse— not specific to the non-modal code path. TooltipandDialogboth work fine in the exact same app/dependency tree with structurally similar composition (Trigger asChild+Portal+ focus-managedContent).- Pinning
@radix-ui/react-slotto1.2.5or1.2.3(full clean reinstalls each time) does not fix it — so this isn't the Slot regression described in #3747 (which was fixed/worked around at the Slot level for a different pattern). - Both
radix-ui(1.6.7) and@radix-ui/react-popover(1.1.23) are already the latest stable releases at the time of filing — no newer version available to try (only1.2.0-rc.*prereleases for@radix-ui/react-popover, and1.7.0-rc.*for theradix-uimeta-package).
Root cause (best guess from reading source)
PopoverContentImpl composes:
FocusScope (asChild) > DismissableLayer (asChild) > PopperPrimitive.ContentDialog composes FocusScope (asChild) > DismissableLayer (asChild) > Primitive.div (no Popper layer) — works fine.
Tooltip composes PopperPrimitive.Content directly, with no FocusScope/DismissableLayer wrapping (tooltips aren't focusable, so this makes sense) — works fine.
Popover is the one primitive combining both FocusScope/DismissableLayer and PopperPrimitive.Content underneath — and it's the one that's broken. That intersection is my best guess at the actual fault line, though I haven't dug further into exactly which prop/ref is losing its single-child shape across that specific chain.
Environment
react: 19.2.8react-dom: 19.2.8radix-ui: 1.6.7 (unified package)@radix-ui/react-popover(resolved): 1.1.23@radix-ui/react-slot(resolved): 1.3.3 (also tried 1.2.5 and 1.2.3 viaoverrides— same failure both times)- Bundler: Vite 8 (also reproduces under Storybook 10.5's Vite builder, separately from the app's own build)
- OS: Windows
Workaround in use
Not using Popover for now — using Dialog with modal={false} and manually-positioned Content (no Popper anchoring) instead, which sidesteps the broken combination entirely.
Source: radix-ui/primitives