slidevjs/slidev · error · Error

Invalid range for v-switch

Error message

Invalid range for v-switch: ${range}

What it means

Thrown by the VSwitch component while parsing its named slot names. Each slot name must be either a single integer (e.g. '1') or a 'start-end' range (e.g. '2-4'); any other string that cannot be split into two finite numbers triggers this. The check happens in the component setup before any rendering logic runs.

Solutions

  1. Rename the slot to a single integer (#1) or a dash-separated range (#1-3)
  2. Remove any non-digit characters from the slot name
  3. If you intended a single-step switch, use a plain integer slot name

Example fix

// before
<template #1..3>...</template>
// after
<template #1-3>...</template>
Defensive patterns

Strategy: validation

Validate before calling

function isValidSwitchSlot(name: string): boolean {
  return /^\d+$/.test(name) || /^\d+-\d+$/.test(name)
}
// before rendering <v-switch>:
Object.keys($slots).forEach(n => { if (!isValidSwitchSlot(n)) throw new Error(`Bad v-switch slot: ${n}`) })

Type guard

function isSwitchSlotName(name: string): name is `${number}` | `${number}-${number}` {
  return /^\d+$/.test(name) || /^\d+-\d+$/.test(name)
}

Prevention

When it happens

Trigger: Defining a <v-switch> with a malformed slot name such as #1..3, #1:3, #1~3, #abc, #1- (trailing dash), or any name containing characters other than digits and a single dash.

Common situations: Copying range syntax from another tool (Python slices use ':', CSS uses '/'), typos in slot names, or stray whitespace/punctuation introduced by editor auto-formatting.


AI-assisted analysis of slidevjs/slidev@0d798ace58 (2026-08-12). Data as JSON: /api/errors/c2d14c12bc486430. Report an issue: GitHub.

Appendix: source

Thrown at packages/client/builtin/VSwitch.ts:50

      type: String,
      default: 'div',
    },
  },
  setup({ at, unmount, transition, tag, childTag }, { slots }) {
    const slotEntries = Object.entries(slots).sort((a, b) => -a[0].split('-')[0] + +b[0].split('-')[0])
    const contents: [start: number, end: number, slot: Slot<any> | undefined, elRef: Ref<HTMLElement | undefined>][] = []

    let lastStart: number | undefined
    for (const [range, slot] of slotEntries) {
      const elRef = ref<HTMLElement>()
      if (Number.isFinite(+range)) {
        contents.push([+range, lastStart ?? +range + 1, slot, elRef])
        lastStart = +range
      }
      else {
        const [start, end] = range.split('-').map(Number)
        if (!Number.isFinite(start) || !Number.isFinite(end))
          throw new Error(`Invalid range for v-switch: ${range}`)
        contents.push([start, end, slot, elRef])
        lastStart = start
      }
    }

    const size = Math.max(...contents.map(c => c[1])) - 1
    const id = makeId()
    const offset = ref(0)

    const { $clicksContext: clicks, $nav: nav } = useSlideContext()

    onMounted(() => {
      const clicksInfo = clicks.calculateSince(at, size)
      if (!clicksInfo) {
        offset.value = CLICKS_MAX
        return
      }
      clicks.register(id, clicksInfo)

View on GitHub (pinned to 0d798ace58)