{"record":{"id":"3624c89758dd0e98","repo":"tailwindlabs/headlessui","slug":"a-dialogbackdrop-component-is-being-used-but","errorCode":null,"errorMessage":"A <DialogBackdrop /> component is being used, but a <DialogPanel /> component is missing.","messagePattern":"A <DialogBackdrop /> component is being used, but a <DialogPanel /> component is missing\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/@headlessui-vue/src/components/dialog/dialog.ts","lineNumber":405,"sourceCode":"\n// ---\n\nexport let DialogBackdrop = defineComponent({\n  name: 'DialogBackdrop',\n  props: {\n    as: { type: [Object, String], default: 'div' },\n    id: { type: String, default: () => `headlessui-dialog-backdrop-${useId()}` },\n  },\n  inheritAttrs: false,\n  setup(props, { attrs, slots, expose }) {\n    let api = useDialogContext('DialogBackdrop')\n    let internalBackdropRef = ref(null)\n\n    expose({ el: internalBackdropRef, $el: internalBackdropRef })\n\n    onMounted(() => {\n      if (api.panelRef.value === null) {\n        throw new Error(\n          `A <DialogBackdrop /> component is being used, but a <DialogPanel /> component is missing.`\n        )\n      }\n    })\n\n    return () => {\n      let { id, ...theirProps } = props\n      let ourProps = {\n        id,\n        ref: internalBackdropRef,\n        'aria-hidden': true,\n      }\n\n      return h(ForcePortalRoot, { force: true }, () =>\n        h(Portal, () =>\n          render({\n            ourProps,\n            theirProps: { ...attrs, ...theirProps },","sourceCodeStart":387,"sourceCodeEnd":423,"githubUrl":"https://github.com/tailwindlabs/headlessui/blob/eea57cf46fd6767ed1059012f7073b88eb159fba/packages/@headlessui-vue/src/components/dialog/dialog.ts#L387-L423","documentation":"When @headlessui-vue's DialogBackdrop mounts, it expects a sibling DialogPanel to exist inside the same Dialog (it wires backdrop click handling and aria wiring against api.panelRef). If panelRef is still null onMounted, the required <DialogPanel /> is missing and the component throws because the backdrop cannot function correctly without it.","triggerScenarios":"Rendering <DialogBackdrop> inside <Dialog> but omitting <DialogPanel>; replacing DialogPanel with a plain <div>; ordering/mounting issues where the panel component is conditionally not rendered.","commonSituations":"Refactoring dialog markup and dropping the DialogPanel wrapper; using DialogBackdrop for styling but keeping content in raw divs; upgrading from patterns where panels were implicit.","solutions":["Add a <DialogPanel> inside the same <Dialog>, containing the dialog's content.","If you replaced DialogPanel with a plain div, switch it back to DialogPanel and style it via its props/class.","Ensure DialogPanel is not wrapped in v-if=\"false\" or lazy-rendered so it exists when the backdrop mounts."],"exampleFix":"// before\n<Dialog :open=\"open\">\n  <DialogBackdrop class=\"bg-black/50\" />\n  <div class=\"...\">...</div>\n</Dialog>\n\n// after\n<Dialog :open=\"open\">\n  <DialogBackdrop class=\"bg-black/50\" />\n  <DialogPanel class=\"...\">...</DialogPanel>\n</Dialog>","handlingStrategy":"validation","validationCode":"// Only render the backdrop when the panel is present in the same Dialog\n<Dialog :open=\"open\">\n  <DialogBackdrop class=\"bg-black/50\" />\n  <DialogPanel v-if=\"hasContent\"><slot /></DialogPanel>\n</Dialog>","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Treat DialogBackdrop/DialogTitle/DialogPanel as a set: never render the backdrop without the panel.","Use a linter/editor snippet that scaffolds the full dialog trio together.","Avoid conditionally removing DialogPanel while the backdrop is mounted."],"tags":["headlessui","vue","dialog","missing-component","dialog-panel"],"backgroundTag":"missing-required-sibling-component","analyzedSha":"eea57cf46fd6767ed1059012f7073b88eb159fba","analyzedAt":"2026-08-28T19:22:46.163Z","schemaVersion":2},"datasetVersion":"2026-08-28T21:17:43.275Z"}