vuetifyjs/vuetify · error · Error
[Vuetify] v-expansion-panel-title needs to be placed inside
Error message
[Vuetify] v-expansion-panel-title needs to be placed inside v-expansion-panel
What it means
VExpansionPanelTitle injects VExpansionPanelSymbol, provided only by <v-expansion-panel>. It throws when <v-expansion-panel-title> is rendered without a <v-expansion-panel> ancestor, since the title needs the panel's selection/expanded state.
Source
Thrown at packages/vuetify/src/components/VExpansionPanel/VExpansionPanelTitle.tsx:73
type: Boolean,
default: true,
},
...makeComponentProps(),
...makeDimensionProps(),
}, 'VExpansionPanelTitle')
export const VExpansionPanelTitle = genericComponent<VExpansionPanelTitleSlots>()({
name: 'VExpansionPanelTitle',
directives: { vRipple },
props: makeVExpansionPanelTitleProps(),
setup (props, { slots }) {
const expansionPanel = inject(VExpansionPanelSymbol)
if (!expansionPanel) throw new Error('[Vuetify] v-expansion-panel-title needs to be placed inside v-expansion-panel')
const { backgroundColorClasses, backgroundColorStyles } = useBackgroundColor(() => props.color)
const { dimensionStyles } = useDimension(props)
const slotProps = computed(() => ({
collapseIcon: props.collapseIcon,
disabled: expansionPanel.disabled.value,
expanded: expansionPanel.isSelected.value,
expandIcon: props.expandIcon,
readonly: props.readonly,
}))
const icon = toRef(() => expansionPanel.isSelected.value ? props.collapseIcon : props.expandIcon)
useRender(() => (
<button
class={[
'v-expansion-panel-title',View on GitHub (pinned to 8d153908df)
Solutions
- Nest <v-expansion-panel-title> inside <v-expansion-panel> (inside <v-expansion-panels>).
- Keep teleported title nodes inside the panel provide tree.
- Wrap the component in <v-expansion-panel> for tests.
Example fix
// before
<v-expansion-panel-title>Title</v-expansion-panel-title>
// after
<v-expansion-panels>
<v-expansion-panel>
<v-expansion-panel-title>Title</v-expansion-panel-title>
</v-expansion-panel>
</v-expansion-panels> Defensive patterns
Strategy: type-guard
Validate before calling
import { inject } from 'vue'
import { VExpansionPanelSymbol } from 'vuetify'
const panel = inject(VExpansionPanelSymbol, null)
if (!panel) {
// not inside a panel: render a plain button instead of v-expansion-panel-title
} Type guard
import { inject } from 'vue'
import { VExpansionPanelSymbol } from 'vuetify'
export function isInsideExpansionPanel (): boolean {
return inject(VExpansionPanelSymbol, null) != null
} Prevention
- Always nest the title inside <v-expansion-panel>.
- Do not teleport the title outside the panel tree.
- Wrap the title in <v-expansion-panel> for tests.
When it happens
Trigger: Placing <v-expansion-panel-title> outside <v-expansion-panel>; teleporting it out of the panel tree; mounting it alone in a test.
Common situations: Markup restructuring that removes the panel wrapper; copy-paste of a title block into another container; building panels dynamically and omitting the wrapper.
Related errors
- [Vuetify] v-expansion-panel-text needs to be placed inside v
- [Vuetify] VOtpField must be used inside VOtpInput
- [Vuetify] v-slider-thumb must be used inside v-slider or v-r
- [Vuetify] v-slider-track must be inside v-slider or v-range-
- [Vuetify] VWindowItem must be used inside VWindow
AI-assisted analysis of vuetifyjs/vuetify@8d153908df (2026-08-12).
Data as JSON: /api/errors/0806796f230654bc.
Report an issue: GitHub.