vuetifyjs/vuetify · error · Error

No samples for touch id ${id}

Error message

No samples for touch id ${id}

What it means

getVelocity(id) reads position samples for a touch identifier from a CircularBuffer keyed by touch.identifier. It throws when touches[id] is undefined, meaning no samples were ever recorded for that id (its touchstart was not captured) or endTouch already deleted the entry.

Source

Thrown at packages/vuetify/src/composables/touch.ts:77

  function addMovement (e: TouchEvent) {
    Array.from(e.changedTouches).forEach(touch => {
      const samples = touches[touch.identifier] ?? (touches[touch.identifier] = new CircularBuffer(HISTORY))
      samples.push([e.timeStamp, touch])
    })
  }

  function endTouch (e: TouchEvent) {
    Array.from(e.changedTouches).forEach(touch => {
      delete touches[touch.identifier]
    })
  }

  function getVelocity (id: number) {
    const samples = touches[id]?.values().reverse()

    if (!samples) {
      throw new Error(`No samples for touch id ${id}`)
    }

    const newest = samples[0]
    const x: Sample[] = []
    const y: Sample[] = []
    for (const val of samples) {
      if (newest[0] - val[0] > HORIZON) break

      x.push({ t: val[0], d: val[1].clientX })
      y.push({ t: val[0], d: val[1].clientY })
    }

    return {
      x: calculateImpulseVelocity(x),
      y: calculateImpulseVelocity(y),
      get direction () {
        const { x, y } = this
        const [absX, absY] = [Math.abs(x), Math.abs(y)]

View on GitHub (pinned to 8d153908df)

Solutions

  1. Ensure the touch-tracking element is mounted before a gesture can begin (do not toggle it with v-if during touch).
  2. If you call getVelocity yourself, guard with the existence of touches[id] first.
  3. Keep pointer-event and touch-event tracking consistent; do not bind/unbind mid-gesture.
Defensive patterns

Strategy: validation

Validate before calling

// If you invoke getVelocity directly, check the sample buffer first.
const samples = touches[id]?.values().reverse()
if (!samples || samples.length === 0) {
  // no data: return zero velocity instead of throwing
  return { x: 0, y: 0 }
}

Type guard

export function hasTouchSamples (touches: Record<number, unknown>, id: number): boolean {
  return touches[id] != null
}

Try / catch

try {
  const v = getVelocity(id)
} catch (e) {
  // touch id had no recorded samples; ignore stale/stray event
  return { x: 0, y: 0 }
}

Prevention

When it happens

Trigger: A touchmove/touchend fires for an identifier whose touchstart the directive never observed; calling getVelocity() manually for an id that has no buffer; endTouch cleared the entry before getVelocity ran; element mounted or v-touch bound during an in-progress gesture.

Common situations: Conditionally rendering (v-if) a v-touch element mid-gesture; SSR hydration timing where the directive binds after the browser dispatches touchstart; a stray touchend arriving from a different target; mixing pointer events and touch events.


AI-assisted analysis of vuetifyjs/vuetify@8d153908df (2026-08-12). Data as JSON: /api/errors/15bbff3a7045bd50. Report an issue: GitHub.