slidevjs/slidev · error · Error

Slide ${no} does not exist. The deck has ${data.slides.lengt

Error message

Slide ${no} does not exist. The deck has ${data.slides.length} slides (1-${data.slides.length}).

What it means

Thrown by resolveSlide(data, no) when data.slides[no - 1] is falsy. Slides are addressed 1-based (matching presentation slide numbers); the error message echoes the valid 1..N range. Every MCP operation tool routes its slide-number argument through this guard.

Source

Thrown at packages/slidev/node/mcp/operations.ts:14

import type { LoadedSlidevData } from '@slidev/parser/fs'
import type { SlideInfo, SlidePatch, SourceSlideInfo } from '@slidev/types'
import * as parser from '@slidev/parser/fs'
import YAML from 'yaml'
import { updateFrontmatterPatch } from '../utils'

/**
 * Resolve a rendered slide (1-based, as displayed in the presentation) or
 * throw a descriptive error.
 */
export function resolveSlide(data: LoadedSlidevData, no: number): SlideInfo {
  const slide = data.slides[no - 1]
  if (!slide)
    throw new Error(`Slide ${no} does not exist. The deck has ${data.slides.length} slides (1-${data.slides.length}).`)
  return slide
}

function getMarkdown(data: LoadedSlidevData, source: SourceSlideInfo) {
  const md = data.markdownFiles[source.filepath]
  if (!md)
    throw new Error(`Markdown file not loaded: ${source.filepath}`)
  return md
}

function assertNotEntryHeadmatter(data: LoadedSlidevData, source: SourceSlideInfo, action: string) {
  if (source.filepath === data.entry.filepath && data.entry.slides.indexOf(source) === 0) {
    throw new Error(
      `Cannot ${action} the first slide of the entry file: its frontmatter is the deck headmatter (global configuration). `
      + `Edit its content with the update tool instead, or operate on the following slides.`,
    )
  }
}

View on GitHub (pinned to 0d798ace58)

Solutions

  1. Call slidev-list-slides again to refresh slide numbers after any insert/remove/move, then retry with a valid number.
  2. Pass a number in the range 1..totalSlides reported by slidev-get-info.
  3. If the caller holds stale state, re-fetch via ctx.getData() before indexing.

Example fix

// before: stale number after a remove
await tools['slidev-remove-slide']({ no: 3 })
await tools['slidev-get-slide']({ no: 5 }) // deck now shorter -> throws

// after: refresh, then index by the new layout
const slides = await tools['slidev-list-slides']({})
const last = slides.at(-1).no
await tools['slidev-get-slide']({ no: last })
Defensive patterns

Strategy: validation

Validate before calling

function assertSlideNo(data: { slides: unknown[] }, no: number): void {
  if (!Number.isInteger(no) || no < 1 || no > data.slides.length) {
    throw new RangeError(`Slide no must be 1..${data.slides.length}, got ${no}`)
  }
}

// before any tool call:
const data = await ctx.getData()
assertSlideNo(data, requestedNo)

Type guard

function isValidSlideNo(no: unknown, total: number): no is number {
  return typeof no === 'number'
    && Number.isInteger(no)
    && no >= 1
    && no <= total
}

Try / catch

try {
  const slide = resolveSlide(data, no)
} catch (e) {
  if (e instanceof Error && /does not exist\./.test(e.message)) {
    // re-list and surface the valid range to the caller/agent
    const total = data.slides.length
    return { error: `invalid slide number; valid range is 1-${total}` }
  }
  throw e
}

Prevention

When it happens

Trigger: Calling any slide-scoped MCP tool (slidev-get-slide, slidev-update-slide, slidev-remove-slide, slidev-move-slide, slidev-goto-slide) with a number greater than data.slides.length, less than 1, or a number that became stale after a prior insert/remove/move shifted the deck.

Common situations: An agent edits the deck (insert/remove) and reuses an old slide number without re-listing; user passes a 0-based index by mistake; hidden/disabled slides shrink the visible count vs. what the caller assumed.

Related errors


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