tailwindlabs/headlessui · warning
Invalid role [${role}] passed to <Dialog />. Only `dialog` a
Error message
Invalid role [${role}] passed to <Dialog />. Only `dialog` and and `alertdialog` are supported. Using `dialog` instead. What it means
This console.warn comes from the Headless UI Vue <Dialog /> component when the `role` prop is set to anything other than 'dialog' or 'alertdialog'. The component falls back to role="dialog" but warns once (a module-level didWarnOnRole flag ensures it only fires a single time). It exists to catch invalid WAI-ARIA dialog roles, since only those two roles are meaningful for a modal dialog.
Source
Thrown at packages/@headlessui-vue/src/components/dialog/dialog.ts:94
id: { type: String, default: () => `headlessui-dialog-${useId()}` },
role: { type: String as PropType<'dialog' | 'alertdialog'>, default: 'dialog' },
},
emits: { close: (_close: boolean) => true },
setup(props, { emit, attrs, slots, expose }) {
let ready = ref(false)
onMounted(() => {
ready.value = true
})
let didWarnOnRole = false
let role = computed(() => {
if (props.role === 'dialog' || props.role === 'alertdialog') {
return props.role
}
if (!didWarnOnRole) {
didWarnOnRole = true
console.warn(
`Invalid role [${role}] passed to <Dialog />. Only \`dialog\` and and \`alertdialog\` are supported. Using \`dialog\` instead.`
)
}
return 'dialog'
})
let nestedDialogCount = ref(0)
let usesOpenClosedState = useOpenClosed()
let open = computed(() => {
if (props.open === Missing && usesOpenClosedState !== null) {
return (usesOpenClosedState.value & State.Open) === State.Open
}
return props.open
})
let internalDialogRef = ref<HTMLDivElement | null>(null)View on GitHub (pinned to eea57cf46f)
Solutions
- Set role to a valid value: <Dialog role="alertdialog"> for destructive/confirmation modals, or omit the prop entirely (defaults to 'dialog').
- If the role is dynamic, ensure the expression is typed as `'dialog' | 'alertdialog'` and has a default: `role="alertdialog"` fallback.
- Check for typos and casing — the comparison is case-sensitive against the exact strings 'dialog' and 'alertdialog'.
Example fix
// before <Dialog role="modal" @close="close"> <!-- warns: Invalid role [modal] --> // after <Dialog role="dialog" @close="close"> <!-- or for confirmation dialogs --> <Dialog role="alertdialog" @close="close">
Defensive patterns
Strategy: type-guard
Validate before calling
const VALID_ROLES = ['dialog', 'alertdialog'] as const const role = computed(() => VALID_ROLES.includes(props.modalRole) ? props.modalRole : 'alertdialog' )
Type guard
type DialogRole = 'dialog' | 'alertdialog'
function isValidDialogRole(role: unknown): role is DialogRole {
return role === 'dialog' || role === 'alertdialog'
} Prevention
- Type modal-role props as `'dialog' | 'alertdialog'` so invalid values fail at compile time.
- Omit the role prop unless you specifically need alertdialog semantics.
- Centralize role constants in one shared module instead of inlining strings.
When it happens
Trigger: Passing a non-standard or misspelled role to <Dialog role="...">, e.g. role="tooltip", role="dialogue", role="Dialog" (case-sensitive), or binding a variable that resolves to undefined/empty string at render time.
Common situations: Dynamically computing the role from a prop or config object that can be undefined; copy-pasting code that used a different role string; upgrading from a version that silently accepted any role; passing a role intended for a different component (e.g. using <Dialog> where <Disclosure> or a custom overlay was meant).
Related errors
- Invalid role [${role}] passed to <Dialog />. Only `dialog` a
- There are no focusable elements inside the <FocusTrap />
- 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
AI-assisted analysis of tailwindlabs/headlessui@eea57cf46f (2026-08-28).
Data as JSON: /api/errors/0176cd18215bd748.
Report an issue: GitHub.