tailwindlabs/headlessui · error · Error
Missing parent
Error message
Missing parent
What it means
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.
Source
Thrown at packages/@headlessui-vue/src/components/description/description.ts:29
type InjectionKey,
type Ref,
} from 'vue'
import { useId } from '../../hooks/use-id'
import { render } from '../../utils/render'
// ---
let DescriptionContext = Symbol('DescriptionContext') as InjectionKey<{
register(value: string): () => void
slot: Ref<Record<string, any>>
name: string
props: Record<string, any>
}>
function useDescriptionContext() {
let context = inject(DescriptionContext, null)
if (context === null) {
throw new Error('Missing parent')
}
return context
}
export function useDescriptions({
slot = ref({}),
name = 'Description',
props = {},
}: {
slot?: Ref<Record<string, unknown>>
name?: string
props?: Record<string, unknown>
} = {}): ComputedRef<string | undefined> {
let descriptionIds = ref<string[]>([])
function register(value: string) {
descriptionIds.value.push(value)
View on GitHub (pinned to eea57cf46f)
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).
Example fix
// before <Description>Read-only input</Description> <Combobox v-model="x">...</Combobox> // after <Combobox v-model="x"> ... <Description>Read-only input</Description> </Combobox>
Defensive patterns
Strategy: validation
Validate before calling
// In Vue: ensure the Description is a descendant of a providing widget before rendering it
<Dialog :open="open">
<!-- only render Description here, inside the provider -->
<Description>{{ text }}</Description>
</Dialog> Try / catch
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 } Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- A <TransitionChild /> is used but it is missing a parent <Tr
- You forgot to provide an `open` prop to the `Dialog`.
- You provided an `open` prop to the `Dialog`, but the value i
- A <DialogBackdrop /> component is being used, but a <DialogP
- [Headless UI]: Cannot find ownerDocument for contextElement:
AI-assisted analysis of tailwindlabs/headlessui@eea57cf46f (2026-08-28).
Data as JSON: /api/errors/c84005b92c8f1f2b.
Report an issue: GitHub.