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 React <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 ref-based didWarnOnRole flag limits it to a single warning). It guards against invalid WAI-ARIA dialog roles, since only those two roles are valid for modals.
Source
Thrown at packages/@headlessui-react/src/components/dialog/dialog.tsx:146
onClose,
initialFocus,
role = 'dialog',
autoFocus = true,
__demoMode = false,
unmount = false,
...theirProps
} = props
let didWarnOnRole = useRef(false)
role = (function () {
if (role === 'dialog' || role === 'alertdialog') {
return role
}
if (!didWarnOnRole.current) {
didWarnOnRole.current = true
console.warn(
`Invalid role [${role}] passed to <Dialog />. Only \`dialog\` and and \`alertdialog\` are supported. Using \`dialog\` instead.`
)
}
return 'dialog'
})()
let usesOpenClosedState = useOpenClosed()
if (open === undefined && usesOpenClosedState !== null) {
// Update the `open` prop based on the open closed state
open = (usesOpenClosedState & State.Open) === State.Open
}
let internalDialogRef = useRef<HTMLElement | null>(null)
let dialogRef = useSyncRefs(internalDialogRef, ref)
let ownerDocument = useOwnerDocument(internalDialogRef.current)
View on GitHub (pinned to eea57cf46f)
Solutions
- Set role to a valid value: <Dialog role="alertdialog"> for confirmation/destructive modals, or omit the prop entirely (defaults to 'dialog').
- Type the variable as `'dialog' | 'alertdialog' | undefined` so TypeScript catches bad values before runtime.
- Audit prop spreads (<Dialog {...props}>) for a stray `role` coming from parent components.
Example fix
// before
<Dialog role="modal" onClose={close}>
{/* warns: Invalid role [modal] */}
// after
<Dialog role="dialog" onClose={close}>
{/* or for confirmation dialogs */}
<Dialog role="alertdialog" onClose={close}> Defensive patterns
Strategy: type-guard
Validate before calling
const VALID_ROLES = ['dialog', 'alertdialog'] as const
// before render
const role = isValidDialogRole(props.modalRole) ? props.modalRole : 'alertdialog'
return <Dialog role={role} onClose={onClose}>...</Dialog> Type guard
type DialogRole = 'dialog' | 'alertdialog'
function isValidDialogRole(role: unknown): role is DialogRole {
return role === 'dialog' || role === 'alertdialog'
} Prevention
- Type role props as `'dialog' | 'alertdialog'` (or omit the prop) so TypeScript rejects bad values.
- Avoid blindly spreading props (<Dialog {...rest}>) that may carry a foreign `role`.
- Use 'alertdialog' only for confirmation/destructive modals per ARIA authoring practices.
When it happens
Trigger: Passing a non-standard or misspelled role to <Dialog role="...">, e.g. role="modal", role="alert-dialog", role="Dialog" (case-sensitive), or a ternary that evaluates to undefined/null instead of a valid string.
Common situations: Spreading props from another component into <Dialog> that includes a conflicting `role`; computing role conditionally (role={isAlert ? 'alertdialog' : undefined} where undefined wasn't intended); upgrading from an older version that accepted arbitrary roles; copy-paste from non-modal overlay code.
Related errors
- Invalid role [${role}] passed to <Dialog />. Only `dialog` a
- There are no focusable elements inside the <FocusTrap />
- You have to provide an `open` and an `onClose` prop to the `
- You provided an `onClose` prop to the `Dialog`, but forgot a
- You provided an `open` prop to the `Dialog`, but forgot an `
AI-assisted analysis of tailwindlabs/headlessui@eea57cf46f (2026-08-28).
Data as JSON: /api/errors/47da4bc9b2463544.
Report an issue: GitHub.