tailwindlabs/headlessui · error · Error
You provided an `open` prop to the `Dialog`, but forgot an `
Error message
You provided an `open` prop to the `Dialog`, but forgot an `onClose` prop.
What it means
The inverse validation: `open` was provided but `onClose` was not (and no OpenClosed context). Dialog needs a callback to signal close requests (Escape key, backdrop click, scroll-lock teardown); without it the dialog would be impossible to dismiss, so it throws.
Source
Thrown at packages/@headlessui-react/src/components/dialog/dialog.tsx:399
// 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(
`You provided an \`onClose\` prop to the \`Dialog\`, but the value is not a function. Received: ${props.onClose}`
)
}
if ((open !== undefined || transition) && !rest.static) {
return (View on GitHub (pinned to eea57cf46f)
Solutions
- Add `<Dialog open={open} onClose={() => setOpen(false)}>`.
- If you truly want it non-dismissible, still pass a no-op: `onClose={() => {}}` and disable outside-click/escape via `static` + custom handling.
- Verify spreads: `<Dialog open={open} {...rest}>` where rest actually contains onClose.
Example fix
// before
<Dialog open={isOpen}>...</Dialog>
// after
<Dialog open={isOpen} onClose={() => setIsOpen(false)}>...</Dialog> Defensive patterns
Strategy: type-guard
Validate before calling
const close = useCallback(() => setOpen(false), [])
// <Dialog open={open} onClose={close}> Type guard
const hasOnClose = (p: { onClose?: unknown }): boolean => typeof p.onClose === 'function' Prevention
- Pair open and onClose in one reusable snippet.
- Use exactly the prop name onClose, not onRequestClose.
- Provide a no-op onClose if dismissal must be disabled.
When it happens
Trigger: `<Dialog open={isOpen}>` with no `onClose`; passing onClose via a spread that evaluates undefined; renaming the handler (e.g., `onCloseRequest`) so the real prop is missing.
Common situations: Initial scaffolding where only `open` was wired; prop drilling typos; using `onRequestClose` (react-native-modal naming) instead of `onClose`.
Related errors
- You have to provide an `open` and an `onClose` prop to the `
- You provided an `onClose` prop to the `Dialog`, but forgot a
- 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/3e0d93ab990238ae.
Report an issue: GitHub.