{"record":{"id":"ea16fc2f079be3bb","repo":"slidevjs/slidev","slug":"slide-from-is-out-of-sync-with-its-source-file","errorCode":null,"errorMessage":"Slide ${from} 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":196,"sourceCode":"  const slide = resolveSlide(data, from)\n  const anchor = resolveSlide(data, anchorNo)\n\n  if (slide.source.filepath !== anchor.source.filepath) {\n    throw new Error(\n      `Cannot move a slide across markdown files: slide ${from} is in \"${slide.source.filepath}\" `\n      + `but slide ${anchorNo} is in \"${anchor.source.filepath}\" (imported with \\`src:\\`). `\n      + `Move it within its own file, or edit the \\`src:\\` imports in the entry file manually.`,\n    )\n  }\n\n  assertNotEntryHeadmatter(data, slide.source, 'move')\n  if (before != null)\n    assertNotEntryHeadmatter(data, anchor.source, 'insert a slide before')\n\n  const md = getMarkdown(data, slide.source)\n  const fromIdx = md.slides.indexOf(slide.source)\n  if (fromIdx < 0)\n    throw new Error(`Slide ${from} is out of sync with its source file. Try again.`)\n  md.slides.splice(fromIdx, 1)\n  const anchorIdx = md.slides.indexOf(anchor.source)\n  if (anchorIdx < 0)\n    throw new Error(`Slide ${anchorNo} is out of sync with its source file. Try again.`)\n  md.slides.splice(before != null ? anchorIdx : anchorIdx + 1, 0, slide.source)\n  const fileContent = await parser.save(md)\n  return { moved: slide, anchor, filepath: md.filepath, fileContent }\n}\n","sourceCodeStart":178,"sourceCodeEnd":205,"githubUrl":"https://github.com/slidevjs/slidev/blob/0d798ace5828966d9f77f62094d5f7a971ad98f7/packages/slidev/node/mcp/operations.ts#L178-L205","documentation":"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.","triggerScenarios":"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.","commonSituations":"Concurrent MCP clients; an editor save interleaving with the tool call; cached getData() across an HMR reload.","solutions":["Re-fetch data with ctx.getData() immediately before moveSlide and retry.","Serialize deck mutations so only one writer touches a given markdown file at a time.","Restart the dev server to rebuild parser state from disk if it persists."],"exampleFix":"// before: stale data reused for a move\nconst data = await ctx.getData()\n// ... another client removes a slide in the same file ...\nawait moveSlide(data, { from: 2, after: 4 }) // throws: from out of sync\n\n// after: re-acquire data per mutation\nconst data = await ctx.getData()\nawait moveSlide(data, { from: 2, after: 4 })","handlingStrategy":"retry","validationCode":"function fromSlideInFile(md: { slides: SourceSlideInfo[] }, source: SourceSlideInfo): boolean {\n  return md.slides.indexOf(source) >= 0\n}\n\n// before moveSlide:\nconst data = await ctx.getData()\nconst slide = resolveSlide(data, from)\nconst md = data.markdownFiles[slide.source.filepath]\nif (!md || !fromSlideInFile(md, slide.source)) return // refresh","typeGuard":"function fromSourceCurrent(md: { slides: SourceSlideInfo[] }, s: SourceSlideInfo): s is SourceSlideInfo {\n  return md.slides.indexOf(s) >= 0\n}","tryCatchPattern":"try {\n  return await moveSlide(data, opts)\n} catch (e) {\n  if (e instanceof Error && new RegExp(`Slide ${opts.from} is out of sync`).test(e.message)) {\n    data = await ctx.getData()\n    return await moveSlide(data, opts)\n  }\n  throw e\n}","preventionTips":["Fetch ctx.getData() immediately before each moveSlide.","Disallow concurrent edits to the same file.","Re-run slidev-list-slides after HMR reloads before moving.","In agent loops, refresh data per iteration."],"tags":["mcp","state","stale-data","move","consistency"],"backgroundTag":null,"analyzedSha":"0d798ace5828966d9f77f62094d5f7a971ad98f7","analyzedAt":"2026-08-12T17:10:56.221Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}