tailwindlabs/headlessui · error · Error
A <Transition /> is used but it is missing a `:show="true |
Error message
A <Transition /> is used but it is missing a `:show="true | false"` prop.
What it means
Headless UI Vue's <Transition> requires an explicit boolean `show` prop to know when to toggle visibility. A `watchEffect` asserts that `show.value` is strictly `true` or `false`; anything else (undefined, null, a string, a number) throws, because the internal visibility TreeState can't be derived from a non-boolean.
Source
Thrown at packages/@headlessui-vue/src/components/transitions/transition.ts:426
beforeEnter: () => true,
afterEnter: () => true,
beforeLeave: () => true,
afterLeave: () => true,
},
setup(props, { emit, attrs, slots }) {
let usesOpenClosedState = useOpenClosed()
let show = computed(() => {
if (props.show === null && usesOpenClosedState !== null) {
return (usesOpenClosedState.value & State.Open) === State.Open
}
return props.show
})
watchEffect(() => {
if (![true, false].includes(show.value)) {
throw new Error('A <Transition /> is used but it is missing a `:show="true | false"` prop.')
}
})
let state = ref(show.value ? TreeStates.Visible : TreeStates.Hidden)
let nestingBag = useNesting(() => {
state.value = TreeStates.Hidden
})
let initial = ref(true)
let transitionBag = {
show,
appear: computed(() => props.appear || !initial.value),
}
onMounted(() => {
watchEffect(() => {
initial.value = falseView on GitHub (pinned to eea57cf46f)
Solutions
- Always pass a strict boolean: `<Transition :show="isOpen">` where `isOpen` is `ref(false)` or computed to boolean.
- If the source value may be undefined, coerce it: `:show="Boolean(open)"` or `:show="!!open"`.
- Initialize the state ref as `ref(false)`, not `ref(null)` or `ref(undefined)`.
- Remember `show="true"` (string) is wrong in Vue; use `:show="true"`.
Example fix
<!-- before --> <Transition show="true"> ... </Transition> <!-- or --> <Transition> ... </Transition> <!-- after --> <Transition :show="isOpen"> ... </Transition>
Defensive patterns
Strategy: validation
Validate before calling
// Vue: ensure a strict boolean before binding <Transition :show="typeof open === 'boolean' ? open : !!open">
Type guard
const isBoolean = (v: unknown): v is boolean => typeof v === 'boolean'
Prevention
- Always bind :show with the leading colon.
- Initialize toggle refs as ref(false).
- Coerce truthy values with !! before passing.
When it happens
Trigger: Using <Transition> without a `:show` binding; binding `:show="undefined"` because the data isn't loaded yet; passing `show="false"` as a string attribute instead of `:show="false"`; binding to a non-boolean ref or a value that starts as null.
Common situations: Copy-pasting <Transition> from docs but forgetting the show prop; using `v-if`-style truthy values (e.g., a count or object) as `show`; async state where `open` is initially undefined; passing string literals without the `:` binding prefix in Vue.
Related errors
- A <TransitionChild /> is used but it is missing a parent <Tr
- Did you forget to passthrough the `ref` to the actual DOM no
- A <Transition /> is used but it is missing a `show={true | f
- Missing parent
- You forgot to provide an `open` prop to the `Dialog`.
AI-assisted analysis of tailwindlabs/headlessui@eea57cf46f (2026-08-28).
Data as JSON: /api/errors/498ff4e807a1aec2.
Report an issue: GitHub.