{"record":{"id":"74bea1db58d93795","repo":"slidevjs/slidev","slug":"markdown-file-not-loaded-source-filepath","errorCode":null,"errorMessage":"Markdown file not loaded: ${source.filepath}","messagePattern":"Markdown file not loaded: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/slidev/node/mcp/operations.ts","lineNumber":21,"sourceCode":"import * as parser from '@slidev/parser/fs'\nimport YAML from 'yaml'\nimport { updateFrontmatterPatch } from '../utils'\n\n/**\n * Resolve a rendered slide (1-based, as displayed in the presentation) or\n * throw a descriptive error.\n */\nexport function resolveSlide(data: LoadedSlidevData, no: number): SlideInfo {\n  const slide = data.slides[no - 1]\n  if (!slide)\n    throw new Error(`Slide ${no} does not exist. The deck has ${data.slides.length} slides (1-${data.slides.length}).`)\n  return slide\n}\n\nfunction getMarkdown(data: LoadedSlidevData, source: SourceSlideInfo) {\n  const md = data.markdownFiles[source.filepath]\n  if (!md)\n    throw new Error(`Markdown file not loaded: ${source.filepath}`)\n  return md\n}\n\nfunction assertNotEntryHeadmatter(data: LoadedSlidevData, source: SourceSlideInfo, action: string) {\n  if (source.filepath === data.entry.filepath && data.entry.slides.indexOf(source) === 0) {\n    throw new Error(\n      `Cannot ${action} the first slide of the entry file: its frontmatter is the deck headmatter (global configuration). `\n      + `Edit its content with the update tool instead, or operate on the following slides.`,\n    )\n  }\n}\n\nexport interface SlidePatchResult {\n  slide: SlideInfo\n  fileContent: string\n}\n\n/**","sourceCodeStart":3,"sourceCodeEnd":39,"githubUrl":"https://github.com/slidevjs/slidev/blob/0d798ace5828966d9f77f62094d5f7a971ad98f7/packages/slidev/node/mcp/operations.ts#L3-L39","documentation":"Thrown by the internal getMarkdown(data, source) helper when data.markdownFiles[source.filepath] is undefined. It signals that the markdown file backing a slide's source was never loaded into the LoadedSlidevData.markdownFiles map, so the operation cannot read or save it.","triggerScenarios":"Calling applySlidePatch / removeSlide / moveSlide / insertSlide for a slide whose source.filepath is not a key in data.markdownFiles. This typically follows a stale ctx.getData() snapshot taken before a file was added/removed/renamed, or a deck whose entry was reloaded but partial-import state was not.","commonSituations":"Concurrent edits to the entry file's src: imports while the MCP tool runs; a slide imported from a file that was since deleted; an MCP client caching data across HMR reloads without re-calling getData().","solutions":["Re-fetch fresh data with ctx.getData() immediately before the operation rather than reusing a cached snapshot.","Confirm the filepath exists in Object.keys(data.markdownFiles) via slidev-get-info before editing.","If a referenced file was deleted, restore it or remove the offending src: import from the entry, then reload."],"exampleFix":"// before: reusing stale data across an external file change\nconst data = await ctx.getData()\n// ... external process deletes the imported file ...\nawait applySlidePatch(data, no, { content: 'x' }) // throws: file not loaded\n\n// after: always re-acquire data per operation\nconst data = await ctx.getData()\nawait applySlidePatch(data, no, { content: 'x' })","handlingStrategy":"validation","validationCode":"function isMarkdownLoaded(data: LoadedSlidevData, filepath: string): boolean {\n  return Object.prototype.hasOwnProperty.call(data.markdownFiles, filepath)\n}\n\n// before operating on a slide source:\nconst data = await ctx.getData()\nif (!isMarkdownLoaded(data, slide.source.filepath)) {\n  data = await ctx.getData() // refresh once\n  if (!isMarkdownLoaded(data, slide.source.filepath)) return\n}","typeGuard":"function markdownFileAvailable(data: LoadedSlidevData, filepath: string): boolean {\n  return !!data.markdownFiles[filepath]\n}","tryCatchPattern":"try {\n  return getMarkdown(data, source)\n} catch (e) {\n  if (e instanceof Error && e.message.startsWith('Markdown file not loaded')) {\n    // refresh data and retry once\n    data = await ctx.getData()\n    return getMarkdown(data, source)\n  }\n  throw e\n}","preventionTips":["Always call ctx.getData() inside the operation handler, not at request start.","Do not cache LoadedSlidevData across HMR cycles or external edits.","Serialize MCP mutations to avoid concurrent file loads.","After any external file change, reload the deck before issuing more edits."],"tags":["mcp","state","stale-data","filesystem"],"backgroundTag":null,"analyzedSha":"0d798ace5828966d9f77f62094d5f7a971ad98f7","analyzedAt":"2026-08-12T17:10:56.221Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}