tailwindlabs/headlessui · error · Error
You provided an `onClose` prop to the `Dialog`, but forgot a
Error message
You provided an `onClose` prop to the `Dialog`, but forgot an `open` prop.
What it means
The Dialog render-time validation found an `onClose` prop but no `open` prop and no OpenClosed context state. Without `open`, the Dialog has no source of truth for visibility, so it refuses to render rather than silently never closing/opening.
Source
Thrown at packages/@headlessui-react/src/components/dialog/dialog.tsx:393
function DialogFn<TTag extends ElementType = typeof DEFAULT_DIALOG_TAG>(
props: DialogProps<TTag>,
ref: Ref<HTMLElement>
) {
let { transition = false, open, ...rest } = props
// Validations
let usesOpenClosedState = useOpenClosed()
let hasOpen = props.hasOwnProperty('open') || usesOpenClosedState !== null
let hasOnClose = props.hasOwnProperty('onClose')
if (!hasOpen && !hasOnClose) {
throw new Error(
`You have to provide an \`open\` and an \`onClose\` prop to the \`Dialog\` component.`
)
}
if (!hasOpen) {
throw new Error(
`You provided an \`onClose\` prop to the \`Dialog\`, but forgot an \`open\` prop.`
)
}
if (!hasOnClose) {
throw new Error(
`You provided an \`open\` prop to the \`Dialog\`, but forgot an \`onClose\` prop.`
)
}
if (!usesOpenClosedState && typeof props.open !== 'boolean') {
throw new Error(
`You provided an \`open\` prop to the \`Dialog\`, but the value is not a boolean. Received: ${props.open}`
)
}
if (typeof props.onClose !== 'function') {
throw new Error(View on GitHub (pinned to eea57cf46f)
Solutions
- Add the boolean: `<Dialog open={isOpen} onClose={handleClose}>`.
- Check conditional spreads to ensure `open` is always included when `onClose` is.
- Remove `defaultOpen`; Dialog is controlled-only.
Example fix
// before
<Dialog onClose={() => setOpen(false)}>...</Dialog>
// after
<Dialog open={open} onClose={() => setOpen(false)}>...</Dialog> Defensive patterns
Strategy: type-guard
Validate before calling
// Always pass open alongside onClose
// <Dialog open={open ?? false} onClose={close}> Type guard
const hasOpenProp = (p: object): boolean => 'open' in p || 'defaultOpen' in p && false /* unsupported */
Prevention
- Pair open and onClose in one snippet/template you reuse.
- Avoid conditional prop spreads that can drop `open`.
When it happens
Trigger: `<Dialog onClose={handleClose}>` without `open`; conditionally spreading props where the `open` key is dropped (`{...(cond ? {open} : {})}`); passing `defaultOpen` (which Dialog doesn't support) instead of `open`.
Common situations: Thinking `defaultOpen` or the presence of onClose implies controlled state; prop spreading bugs with conditional objects; migrating from Radix/native dialog APIs.
Related errors
- You have to provide an `open` and an `onClose` prop to the `
- You provided an `open` prop to the `Dialog`, but forgot an `
- You provided an `onClose` prop to the `Dialog`, but the valu
- You forgot to provide an `open` prop to the `Dialog`.
- Missing `options` in virtual mode
AI-assisted analysis of tailwindlabs/headlessui@eea57cf46f (2026-08-28).
Data as JSON: /api/errors/fb83f4be19983485.
Report an issue: GitHub.