tailwindlabs/headlessui · error · Error
Passing props on "template"! The current component <${name}
Error message
Passing props on "template"!
The current component <${name} /> is rendering a "template".
However we need to passthrough the following props:
- ${line}
You can apply a few solutions:
- Add an `as="..."` prop, to ensure that we render an actual element instead of a "template".
- Render a single element as the child so that we can forward the props onto that element. What it means
When a Headless UI Vue component renders with `as="template"`, it must forward its props onto a single valid child element. `_render` throws when there are incoming props/attrs to passthrough but the children are not exactly one valid element (no children, multiple children, or text/fragment roots), because there is no unambiguous place to put the props.
Source
Thrown at packages/@headlessui-vue/src/utils/render.ts:117
if (typeof v === 'boolean') {
exposeState = true
}
if (v === true) {
states.push(k)
}
}
if (exposeState) dataAttributes[`data-headlessui-state`] = states.join(' ')
}
if (as === 'template') {
children = flattenFragments(children ?? [])
if (Object.keys(incomingProps).length > 0 || Object.keys(attrs).length > 0) {
let [firstChild, ...other] = children ?? []
if (!isValidElement(firstChild) || other.length > 0) {
throw new Error(
[
'Passing props on "template"!',
'',
`The current component <${name} /> is rendering a "template".`,
`However we need to passthrough the following props:`,
Object.keys(incomingProps)
.concat(Object.keys(attrs))
.map((name) => name.trim())
.filter((current, idx, all) => all.indexOf(current) === idx)
.sort((a, z) => a.localeCompare(z))
.map((line) => ` - ${line}`)
.join('\n'),
'',
'You can apply a few solutions:',
[
'Add an `as="..."` prop, to ensure that we render an actual element instead of a "template".',
'Render a single element as the child so that we can forward the props onto that element.',
]View on GitHub (pinned to eea57cf46f)
Solutions
- Render exactly one real element as the sole child of the template-rendered component: `<PopoverButton as="template"><button>...</button></PopoverButton>`.
- Or drop `as="template"` and set `as="div"` (or the desired tag) so the component renders its own element and attaches props itself.
- Remove extra passthrough props/listeners if you intended a fragment render (not recommended; you lose a11y attrs).
Example fix
<!-- before --> <PopoverButton as="template"> <span>More</span> <Icon icon="chevron" /> </PopoverButton> <!-- after --> <PopoverButton as="template"> <button>More <Icon icon="chevron" /></button> </PopoverButton>
Defensive patterns
Strategy: validation
Validate before calling
// Ensure the as="template" component has exactly one element child before rendering // e.g. structure: <Comp as="template"><div>...</div></Comp>
Prevention
- Always give template-rendered components exactly one element child.
- Prefer as="div" when unsure.
- Keep custom child components single-rooted so attrs can be forwarded.
When it happens
Trigger: Using `as="template"` with zero children, multiple children, or a text node as the child while the component has props to forward (id, class, aria-*, data-* attributes, event listeners).
Common situations: `<DialogOverlay as="template">` wrapping multiple elements; `<PopoverButton as="template"><MyCustomButton/></PopoverButton>` where the child is a component fragment; passing extra attrs to a template-rendered component whose slot content is empty or a plain string.
Related errors
- Missing parent
- You forgot to provide an `open` prop to the `Dialog`.
- You provided an `open` prop to the `Dialog`, but the value i
- A <DialogBackdrop /> component is being used, but a <DialogP
- [Headless UI]: Cannot find ownerDocument for contextElement:
AI-assisted analysis of tailwindlabs/headlessui@eea57cf46f (2026-08-28).
Data as JSON: /api/errors/e16c093354e6ae54.
Report an issue: GitHub.