{"record":{"id":"2fb357c39253aba5","repo":"tailwindlabs/headlessui","slug":"you-forgot-to-provide-an-open-prop-to-the-dialo","errorCode":null,"errorMessage":"You forgot to provide an `open` prop to the `Dialog`.","messagePattern":"You forgot to provide an `open` prop to the `Dialog`\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/@headlessui-vue/src/components/dialog/dialog.ts","lineNumber":122,"sourceCode":"    let usesOpenClosedState = useOpenClosed()\n    let open = computed(() => {\n      if (props.open === Missing && usesOpenClosedState !== null) {\n        return (usesOpenClosedState.value & State.Open) === State.Open\n      }\n      return props.open\n    })\n\n    let internalDialogRef = ref<HTMLDivElement | null>(null)\n\n    let ownerDocument = computed(() => getOwnerDocument(internalDialogRef))\n\n    expose({ el: internalDialogRef, $el: internalDialogRef })\n\n    // Validations\n    let hasOpen = props.open !== Missing || usesOpenClosedState !== null\n\n    if (!hasOpen) {\n      throw new Error(`You forgot to provide an \\`open\\` prop to the \\`Dialog\\`.`)\n    }\n\n    if (typeof open.value !== 'boolean') {\n      throw new Error(\n        `You provided an \\`open\\` prop to the \\`Dialog\\`, but the value is not a boolean. Received: ${\n          open.value === Missing ? undefined : props.open\n        }`\n      )\n    }\n\n    let dialogState = computed(() =>\n      !ready.value ? DialogStates.Closed : open.value ? DialogStates.Open : DialogStates.Closed\n    )\n    let enabled = computed(() => dialogState.value === DialogStates.Open)\n\n    let hasNestedDialogs = computed(() => nestedDialogCount.value > 1) // 1 is the current dialog\n    let hasParentDialog = inject(DialogContext, null) !== null\n    let [portals, PortalWrapper] = useNestedPortals()","sourceCodeStart":104,"sourceCodeEnd":140,"githubUrl":"https://github.com/tailwindlabs/headlessui/blob/eea57cf46fd6767ed1059012f7073b88eb159fba/packages/@headlessui-vue/src/components/dialog/dialog.ts#L104-L140","documentation":"The @headlessui-vue Dialog requires a controlled open state. In setup() it checks whether the open prop was provided or whether the Dialog is inside an OpenClosed-state provider (like Popover or Disclosure panels that render Dialog-like overlays). If neither is present, the Dialog cannot know whether it is open, so it throws this validation error.","triggerScenarios":"Rendering <Dialog> with no open prop and no v-model:open; using <Dialog> outside a component that provides open/closed state; misspelling the prop (e.g. :isOpen) so it is never received.","commonSituations":"Migrating from v1 of Headless UI Vue where `open` was optional; copy-pasting examples that rely on a parent Popover context; forgetting the prop when converting an always-open dialog.","solutions":["Pass the required prop: <Dialog :open=\"isOpen\" @close=\"isOpen = false\">.","If the Dialog is inside a Popover/Disclosure-driven overlay, keep that parent so OpenClosed state is provided.","Check for typos in the prop name (must be exactly `open`)."],"exampleFix":"// before\n<Dialog @close=\"() => {}\">...</Dialog>\n\n// after\n<Dialog :open=\"isOpen\" @close=\"isOpen = false\">...</Dialog>","handlingStrategy":"validation","validationCode":"// Vue 3 script setup\nconst props = defineProps<{ open?: boolean }>()\nif (props.open === undefined && !insideOpenClosedProvider) {\n  // supply a default before rendering <Dialog>\n  props.open = false\n}","typeGuard":"const hasOpenProp = (p: { open?: unknown }): p is { open: boolean } => 'open' in p","tryCatchPattern":"Wrap first Dialog render in an ErrorBoundary (React pattern) or guard with v-if=\"open !== undefined\" so the component only mounts with a valid prop.","preventionTips":["Always write <Dialog :open=\"isOpen\" @close=\"...\"> and let your editor's prop typing validate it.","Define open as a required boolean prop in wrapper components so Vue warns before Headless UI throws.","Don't rely on implicit open/closed state unless the Dialog is genuinely inside a Popover/Disclosure overlay."],"tags":["headlessui","vue","dialog","required-prop","controlled-component"],"backgroundTag":"missing-required-prop","analyzedSha":"eea57cf46fd6767ed1059012f7073b88eb159fba","analyzedAt":"2026-08-28T19:22:46.163Z","schemaVersion":2},"datasetVersion":"2026-08-28T21:17:43.275Z"}