slidevjs/slidev · error · Error

Slide ${no} is out of sync with its source file. Try again.

Error message

Slide ${no} is out of sync with its source file. Try again.

What it means

Thrown by removeSlide when md.slides.indexOf(slide.source) returns -1, i.e. the rendered slide's SourceSlideInfo object is not a member of its own markdown file's slides array. This is an internal consistency check indicating the in-memory deck is out of sync with its source.

Source

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

  return { source, filepath: md.filepath, fileContent }
}

export interface RemoveSlideResult {
  removed: SlideInfo
  filepath: string
  fileContent: string
}

/**
 * Remove a slide from its source markdown file.
 */
export async function removeSlide(data: LoadedSlidevData, no: number): Promise<RemoveSlideResult> {
  const slide = resolveSlide(data, no)
  assertNotEntryHeadmatter(data, slide.source, 'remove')
  const md = getMarkdown(data, slide.source)
  const idx = md.slides.indexOf(slide.source)
  if (idx < 0)
    throw new Error(`Slide ${no} is out of sync with its source file. Try again.`)
  md.slides.splice(idx, 1)
  const fileContent = await parser.save(md)
  return { removed: slide, filepath: md.filepath, fileContent }
}

export interface MoveSlideOptions {
  /** Rendered slide number (1-based) of the slide to move */
  from: number
  /** Move the slide right before this rendered slide number */
  before?: number
  /** Move the slide right after this rendered slide number */
  after?: number
}

export interface MoveSlideResult {
  moved: SlideInfo
  anchor: SlideInfo
  filepath: string

View on GitHub (pinned to 0d798ace58)

Solutions

  1. Re-fetch data via ctx.getData() immediately before removeSlide and retry.
  2. Avoid concurrent edits to the same markdown file while an MCP operation is in flight.
  3. If the error persists, reload the dev server so parser state is rebuilt from disk.

Example fix

// before: cached data across an external edit
const data = await ctx.getData()
// external editor saves slides.md, shifting indices
await removeSlide(data, 3) // throws: out of sync

// after: fresh data per mutation
const data = await ctx.getData()
await removeSlide(data, 3)
Defensive patterns

Strategy: retry

Validate before calling

function slideInFile(md: { slides: SourceSlideInfo[] }, source: SourceSlideInfo): boolean {
  return md.slides.indexOf(source) >= 0
}

// before removeSlide, with fresh data:
const data = await ctx.getData()
const slide = resolveSlide(data, no)
const md = data.markdownFiles[slide.source.filepath]
if (!md || !slideInFile(md, slide.source)) {
  // refresh and abort if still stale
  return
}

Type guard

function slideSourceIsCurrent(
  md: { slides: SourceSlideInfo[] },
  source: SourceSlideInfo,
): source is SourceSlideInfo {
  return md.slides.indexOf(source) >= 0
}

Try / catch

try {
  return await removeSlide(data, no)
} catch (e) {
  if (e instanceof Error && /out of sync/.test(e.message)) {
    data = await ctx.getData() // one refresh+retry
    return await removeSlide(data, no)
  }
  throw e
}

Prevention

When it happens

Trigger: Calling removeSlide(data, no) after the underlying markdown file was edited externally (or by another tool) without refreshing data, so slide.source is a stale object reference no longer present in md.slides.

Common situations: Two concurrent MCP clients editing the same deck; an editor save + HMR reload interleaving with the tool call; reusing a getData() snapshot across a save.

Related errors


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