slidevjs/slidev · error · Error

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

Error message

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

What it means

Thrown by moveSlide when md.slides.indexOf(slide.source) < 0, i.e. the 'from' slide's SourceSlideInfo is not found in its markdown file's slides array. An internal consistency guard analogous to the one in removeSlide, indicating the in-memory state diverged from disk.

Source

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

  const slide = resolveSlide(data, from)
  const anchor = resolveSlide(data, anchorNo)

  if (slide.source.filepath !== anchor.source.filepath) {
    throw new Error(
      `Cannot move a slide across markdown files: slide ${from} is in "${slide.source.filepath}" `
      + `but slide ${anchorNo} is in "${anchor.source.filepath}" (imported with \`src:\`). `
      + `Move it within its own file, or edit the \`src:\` imports in the entry file manually.`,
    )
  }

  assertNotEntryHeadmatter(data, slide.source, 'move')
  if (before != null)
    assertNotEntryHeadmatter(data, anchor.source, 'insert a slide before')

  const md = getMarkdown(data, slide.source)
  const fromIdx = md.slides.indexOf(slide.source)
  if (fromIdx < 0)
    throw new Error(`Slide ${from} is out of sync with its source file. Try again.`)
  md.slides.splice(fromIdx, 1)
  const anchorIdx = md.slides.indexOf(anchor.source)
  if (anchorIdx < 0)
    throw new Error(`Slide ${anchorNo} is out of sync with its source file. Try again.`)
  md.slides.splice(before != null ? anchorIdx : anchorIdx + 1, 0, slide.source)
  const fileContent = await parser.save(md)
  return { moved: slide, anchor, filepath: md.filepath, fileContent }
}

View on GitHub (pinned to 0d798ace58)

Solutions

  1. Re-fetch data with ctx.getData() immediately before moveSlide and retry.
  2. Serialize deck mutations so only one writer touches a given markdown file at a time.
  3. Restart the dev server to rebuild parser state from disk if it persists.

Example fix

// before: stale data reused for a move
const data = await ctx.getData()
// ... another client removes a slide in the same file ...
await moveSlide(data, { from: 2, after: 4 }) // throws: from out of sync

// after: re-acquire data per mutation
const data = await ctx.getData()
await moveSlide(data, { from: 2, after: 4 })
Defensive patterns

Strategy: retry

Validate before calling

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

// before moveSlide:
const data = await ctx.getData()
const slide = resolveSlide(data, from)
const md = data.markdownFiles[slide.source.filepath]
if (!md || !fromSlideInFile(md, slide.source)) return // refresh

Type guard

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

Try / catch

try {
  return await moveSlide(data, opts)
} catch (e) {
  if (e instanceof Error && new RegExp(`Slide ${opts.from} is out of sync`).test(e.message)) {
    data = await ctx.getData()
    return await moveSlide(data, opts)
  }
  throw e
}

Prevention

When it happens

Trigger: Calling moveSlide after the source markdown file was externally edited (or edited by another tool) without refreshing data, so the from slide's source object reference is stale.

Common situations: Concurrent MCP clients; an editor save interleaving with the tool call; cached getData() across an HMR reload.

Related errors


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