tailwindlabs/headlessui · error · Error
You have to provide an `open` and an `onClose` prop to the `
Error message
You have to provide an `open` and an `onClose` prop to the `Dialog` component.
What it means
Headless UI React's Dialog is designed for controlled usage: it must know when it's open (`open`) and how to close (`onClose`). During render it checks `props.hasOwnProperty('open')` (or that an OpenClosed context provider supplies state) and `props.hasOwnProperty('onClose')`; if neither is present it throws this combined error.
Source
Thrown at packages/@headlessui-react/src/components/dialog/dialog.tsx:387
autoFocus?: boolean
transition?: boolean
__demoMode?: boolean
}
>
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(View on GitHub (pinned to eea57cf46f)
Solutions
- Control the Dialog: `<Dialog open={isOpen} onClose={close}>...`.
- Or wrap the Dialog in an OpenClosedProvider-based component (e.g., DialogPanel inside a parent transition) if using the nested APIs.
- If you wanted an uncontrolled dialog, track the boolean yourself in useState and pass it explicitly.
Example fix
// before
<Dialog>...</Dialog>
// after
const [isOpen, setIsOpen] = useState(false)
<Dialog open={isOpen} onClose={() => setIsOpen(false)}>...</Dialog> Defensive patterns
Strategy: type-guard
Validate before calling
const [isOpen, setIsOpen] = useState(false)
// <Dialog open={isOpen} onClose={() => setIsOpen(false)}> Type guard
const hasDialogProps = (p: { open?: unknown; onClose?: unknown }) => 'open' in p && 'onClose' in p Prevention
- Always set up open/onClose as a pair when scaffolding a Dialog.
- Remember Dialog is controlled-only; there is no defaultOpen.
When it happens
Trigger: `<Dialog>...</Dialog>` with neither an `open` prop nor an `onClose` handler; attempting uncontrolled usage, which Dialog does not support.
Common situations: Copy-pasting a Dialog shell from examples and forgetting the props; assuming Dialog has an uncontrolled `open` default like native <dialog>; using Dialog with a state manager that passes props conditionally so both end up omitted.
Related errors
- You provided an `onClose` prop to the `Dialog`, but forgot a
- 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/054b9f507bb98258.
Report an issue: GitHub.