{"record":{"id":"74ea9d6dacced3fc","repo":"slidevjs/slidev","slug":"slide-no-is-out-of-sync-with-its-source-file-t","errorCode":null,"errorMessage":"Slide ${no} is out of sync with its source file. Try again.","messagePattern":"Slide (.+?) is out of sync with its source file\\. Try again\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/slidev/node/mcp/operations.ts","lineNumber":144,"sourceCode":"  return { source, filepath: md.filepath, fileContent }\n}\n\nexport interface RemoveSlideResult {\n  removed: SlideInfo\n  filepath: string\n  fileContent: string\n}\n\n/**\n * Remove a slide from its source markdown file.\n */\nexport async function removeSlide(data: LoadedSlidevData, no: number): Promise<RemoveSlideResult> {\n  const slide = resolveSlide(data, no)\n  assertNotEntryHeadmatter(data, slide.source, 'remove')\n  const md = getMarkdown(data, slide.source)\n  const idx = md.slides.indexOf(slide.source)\n  if (idx < 0)\n    throw new Error(`Slide ${no} is out of sync with its source file. Try again.`)\n  md.slides.splice(idx, 1)\n  const fileContent = await parser.save(md)\n  return { removed: slide, filepath: md.filepath, fileContent }\n}\n\nexport interface MoveSlideOptions {\n  /** Rendered slide number (1-based) of the slide to move */\n  from: number\n  /** Move the slide right before this rendered slide number */\n  before?: number\n  /** Move the slide right after this rendered slide number */\n  after?: number\n}\n\nexport interface MoveSlideResult {\n  moved: SlideInfo\n  anchor: SlideInfo\n  filepath: string","sourceCodeStart":126,"sourceCodeEnd":162,"githubUrl":"https://github.com/slidevjs/slidev/blob/0d798ace5828966d9f77f62094d5f7a971ad98f7/packages/slidev/node/mcp/operations.ts#L126-L162","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Re-fetch data via ctx.getData() immediately before removeSlide and retry.","Avoid concurrent edits to the same markdown file while an MCP operation is in flight.","If the error persists, reload the dev server so parser state is rebuilt from disk."],"exampleFix":"// before: cached data across an external edit\nconst data = await ctx.getData()\n// external editor saves slides.md, shifting indices\nawait removeSlide(data, 3) // throws: out of sync\n\n// after: fresh data per mutation\nconst data = await ctx.getData()\nawait removeSlide(data, 3)","handlingStrategy":"retry","validationCode":"function slideInFile(md: { slides: SourceSlideInfo[] }, source: SourceSlideInfo): boolean {\n  return md.slides.indexOf(source) >= 0\n}\n\n// before removeSlide, with fresh data:\nconst data = await ctx.getData()\nconst slide = resolveSlide(data, no)\nconst md = data.markdownFiles[slide.source.filepath]\nif (!md || !slideInFile(md, slide.source)) {\n  // refresh and abort if still stale\n  return\n}","typeGuard":"function slideSourceIsCurrent(\n  md: { slides: SourceSlideInfo[] },\n  source: SourceSlideInfo,\n): source is SourceSlideInfo {\n  return md.slides.indexOf(source) >= 0\n}","tryCatchPattern":"try {\n  return await removeSlide(data, no)\n} catch (e) {\n  if (e instanceof Error && /out of sync/.test(e.message)) {\n    data = await ctx.getData() // one refresh+retry\n    return await removeSlide(data, no)\n  }\n  throw e\n}","preventionTips":["Call ctx.getData() per mutation; do not reuse snapshots.","Serialize MCP writers per markdown file.","Pause external editors while batch-editing via MCP.","After HMR reloads, re-fetch data before the next op."],"tags":["mcp","state","stale-data","consistency"],"backgroundTag":null,"analyzedSha":"0d798ace5828966d9f77f62094d5f7a971ad98f7","analyzedAt":"2026-08-12T17:10:56.221Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}