{"record":{"id":"00518b45599abee8","repo":"tailwindlabs/headlessui","slug":"you-provided-an-onclose-prop-to-the-dialog-bu-00518b","errorCode":null,"errorMessage":"You provided an `onClose` prop to the `Dialog`, but the value is not a function. Received: ${props.onClose}","messagePattern":"You provided an `onClose` prop to the `Dialog`, but the value is not a function\\. Received: (.+?)","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"critical","filePath":"packages/@headlessui-react/src/components/dialog/dialog.tsx","lineNumber":411,"sourceCode":"    throw new Error(\n      `You provided an \\`onClose\\` prop to the \\`Dialog\\`, but forgot an \\`open\\` prop.`\n    )\n  }\n\n  if (!hasOnClose) {\n    throw new Error(\n      `You provided an \\`open\\` prop to the \\`Dialog\\`, but forgot an \\`onClose\\` prop.`\n    )\n  }\n\n  if (!usesOpenClosedState && typeof props.open !== 'boolean') {\n    throw new Error(\n      `You provided an \\`open\\` prop to the \\`Dialog\\`, but the value is not a boolean. Received: ${props.open}`\n    )\n  }\n\n  if (typeof props.onClose !== 'function') {\n    throw new Error(\n      `You provided an \\`onClose\\` prop to the \\`Dialog\\`, but the value is not a function. Received: ${props.onClose}`\n    )\n  }\n\n  if ((open !== undefined || transition) && !rest.static) {\n    return (\n      <MainTreeProvider>\n        <Transition show={open} transition={transition} unmount={rest.unmount}>\n          <InternalDialog ref={ref} {...rest} />\n        </Transition>\n      </MainTreeProvider>\n    )\n  }\n\n  return (\n    <MainTreeProvider>\n      <InternalDialog ref={ref} open={open} {...rest} />\n    </MainTreeProvider>","sourceCodeStart":393,"sourceCodeEnd":429,"githubUrl":"https://github.com/tailwindlabs/headlessui/blob/eea57cf46fd6767ed1059012f7073b88eb159fba/packages/@headlessui-react/src/components/dialog/dialog.tsx#L393-L429","documentation":"Headless UI's Dialog is a controlled component: it requires an onClose callback prop so it can inform you when the user requests the dialog to close (Escape key, backdrop click, focus-trap interactions). During render, DialogFn validates that props.onClose is actually a function and throws immediately if not. This is a fail-fast guard because a missing onClose leaves the dialog permanently stuck open.","triggerScenarios":"Rendering <Dialog open={...}> without an onClose prop; passing onClose={null} or onClose={undefined} (e.g. conditionally spreading props); passing a value like onClose={dialogState.close} where dialogState is undefined so the value evaluates to undefined; passing a string or other non-function by typo.","commonSituations":"Converting an uncontrolled example to TypeScript and dropping the prop; copying Dialog from docs but forgetting the close handler; spreading {...rest} that overwrites onClose with undefined; version upgrades where prop types became stricter (onClose required).","solutions":["Add (or fix) the onClose prop: <Dialog open={isOpen} onClose={() => setIsOpen(false)}>","If conditionally rendering props, ensure onClose is always a function, e.g. onClose={handleClose ?? (() => {})}","Check that the handler you pass actually exists (no typos like onclose or onCloseHandler undefined at runtime)","In TypeScript, don't cast props to any when wrapping Dialog — keep the required onClose in your wrapper's own props"],"exampleFix":"// before\n<Dialog open={isOpen}>\n  <Dialog.Panel>...</Dialog.Panel>\n</Dialog>\n\n// after\n<Dialog open={isOpen} onClose={() => setIsOpen(false)}>\n  <Dialog.Panel>...</Dialog.Panel>\n</Dialog>","handlingStrategy":"type-guard","validationCode":"const canRenderDialog = typeof onClose === 'function' && typeof open === 'boolean';\nreturn canRenderDialog ? <Dialog open={open} onClose={onClose}>...</Dialog> : null;","typeGuard":"const isDialogProps = (p) =>\n  typeof p.open === 'boolean' && typeof p.onClose === 'function';","tryCatchPattern":null,"preventionTips":["Type your wrapper's props so onClose is required (no optional marker)","Default onClose in wrappers: onClose = () => {}","Add a dev-only assertion before rendering Dialog"],"tags":["headlessui","react","dialog","props","controlled-component"],"backgroundTag":"missing-required-prop","analyzedSha":"eea57cf46fd6767ed1059012f7073b88eb159fba","analyzedAt":"2026-08-28T19:22:46.163Z","schemaVersion":2},"datasetVersion":"2026-08-28T21:17:43.275Z"}