{"record":{"id":"c84005b92c8f1f2b","repo":"tailwindlabs/headlessui","slug":"missing-parent","errorCode":null,"errorMessage":"Missing parent","messagePattern":"Missing parent","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/@headlessui-vue/src/components/description/description.ts","lineNumber":29,"sourceCode":"  type InjectionKey,\n  type Ref,\n} from 'vue'\nimport { useId } from '../../hooks/use-id'\nimport { render } from '../../utils/render'\n\n// ---\n\nlet DescriptionContext = Symbol('DescriptionContext') as InjectionKey<{\n  register(value: string): () => void\n  slot: Ref<Record<string, any>>\n  name: string\n  props: Record<string, any>\n}>\n\nfunction useDescriptionContext() {\n  let context = inject(DescriptionContext, null)\n  if (context === null) {\n    throw new Error('Missing parent')\n  }\n  return context\n}\n\nexport function useDescriptions({\n  slot = ref({}),\n  name = 'Description',\n  props = {},\n}: {\n  slot?: Ref<Record<string, unknown>>\n  name?: string\n  props?: Record<string, unknown>\n} = {}): ComputedRef<string | undefined> {\n  let descriptionIds = ref<string[]>([])\n\n  function register(value: string) {\n    descriptionIds.value.push(value)\n","sourceCodeStart":11,"sourceCodeEnd":47,"githubUrl":"https://github.com/tailwindlabs/headlessui/blob/eea57cf46fd6767ed1059012f7073b88eb159fba/packages/@headlessui-vue/src/components/description/description.ts#L11-L47","documentation":"In @headlessui-vue, Description-related composables inject a DescriptionContext that is provided by a parent component (Dialog, Combobox, Listbox, RadioGroup, etc.). useDescriptionContext() throws 'Missing parent' when inject() returns null, meaning the Description is being rendered outside any component that provides the description context.","triggerScenarios":"Rendering <Description> as a standalone component not nested inside <Dialog>, <Combobox>, <Listbox>, or another providing parent; moving Description markup out of the parent during refactor; rendering it in a Teleport/portal that escapes the provide/inject tree in some setups.","commonSituations":"Extracting description text into a separate component file and forgetting it must stay inside the widget; restructuring templates so the Description ends up a sibling instead of a descendant of the provider component.","solutions":["Move the <Description> (or code using useDescriptions) inside the parent widget that provides the context, e.g. inside <Dialog>...</Dialog>.","If you need a custom component to host the Description, ensure it is rendered as a descendant of the providing component so Vue's provide/inject can resolve.","Check that the parent is the matching headlessui component version (mixed versions can fail to provide context)."],"exampleFix":"// before\n<Description>Read-only input</Description>\n<Combobox v-model=\"x\">...</Combobox>\n\n// after\n<Combobox v-model=\"x\">\n  ...\n  <Description>Read-only input</Description>\n</Combobox>","handlingStrategy":"validation","validationCode":"// In Vue: ensure the Description is a descendant of a providing widget before rendering it\n<Dialog :open=\"open\">\n  <!-- only render Description here, inside the provider -->\n  <Description>{{ text }}</Description>\n</Dialog>","typeGuard":null,"tryCatchPattern":"try { useDescriptions() } catch (e) { if (e instanceof Error && e.message === 'Missing parent') { /* fall back to a plain <p> with id and manual aria-describedby */ } else throw e }","preventionTips":["Keep <Description> markup nested inside the owning widget (Dialog/Combobox/Listbox/RadioGroup).","When extracting Description into its own component, import and place it within the parent's default slot.","Review template structure after refactors to confirm provide/inject ancestry is intact."],"tags":["headlessui","vue","provide-inject","context","description"],"backgroundTag":"missing-parent-context-provider","analyzedSha":"eea57cf46fd6767ed1059012f7073b88eb159fba","analyzedAt":"2026-08-28T19:22:46.163Z","schemaVersion":2},"datasetVersion":"2026-08-28T21:17:43.275Z"}