{"record":{"id":"528b4d5d130d30b2","repo":"slidevjs/slidev","slug":"specify-exactly-one-of-before-or-after","errorCode":null,"errorMessage":"Specify exactly one of `before` or `after`.","messagePattern":"Specify exactly one of `before` or `after`\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/slidev/node/mcp/operations.ts","lineNumber":172,"sourceCode":"  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\n  fileContent: string\n}\n\n/**\n * Move a slide before or after another slide within the same markdown file.\n */\nexport async function moveSlide(data: LoadedSlidevData, options: MoveSlideOptions): Promise<MoveSlideResult> {\n  const { from, before, after } = options\n  if ((before == null) === (after == null))\n    throw new Error('Specify exactly one of `before` or `after`.')\n\n  const anchorNo = (before ?? after)!\n  if (anchorNo === from)\n    throw new Error('The `before`/`after` anchor must be a different slide than `from`.')\n\n  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)","sourceCodeStart":154,"sourceCodeEnd":190,"githubUrl":"https://github.com/slidevjs/slidev/blob/0d798ace5828966d9f77f62094d5f7a971ad98f7/packages/slidev/node/mcp/operations.ts#L154-L190","documentation":"Thrown by moveSlide when (before == null) === (after == null), i.e. the caller supplied both before and after, or neither. The tool requires exactly one anchor so the insertion point is unambiguous.","triggerScenarios":"Calling slidev-move-slide (or moveSlide) with both before and after set, or with both omitted.","commonSituations":"An agent defaults both fields to undefined; a client serializes an empty object as {before: null, after: null}; misunderstanding that exactly one anchor is mandatory.","solutions":["Provide exactly one of before (move to just before that slide) or after (move to just after that slide).","If you only have a target position, compute one anchor and omit the other entirely (do not pass null)."],"exampleFix":"// before: ambiguous - both anchors\nawait tools['slidev-move-slide']({ from: 2, before: 5, after: 5 }) // throws\n\n// after: exactly one anchor\nawait tools['slidev-move-slide']({ from: 2, before: 5 })","handlingStrategy":"validation","validationCode":"function exactlyOneAnchor(opts: { before?: number; after?: number }): boolean {\n  return (opts.before != null) !== (opts.after != null)\n}\n\n// before moveSlide:\nif (!exactlyOneAnchor({ before, after })) {\n  throw new Error('Pass exactly one of `before` or `after`.')\n}","typeGuard":"function hasSingleAnchor(o: unknown): o is { before?: number; after?: number } {\n  if (!o || typeof o !== 'object') return false\n  const { before, after } = o as any\n  return (before != null) !== (after != null)\n}","tryCatchPattern":"try {\n  await moveSlide(data, { from, before, after })\n} catch (e) {\n  if (e instanceof Error && e.message === 'Specify exactly one of `before` or `after`.') {\n    // pick a sensible default anchor and retry, or prompt the caller\n    return { error: 'Ambiguous move: provide exactly one of before/after.' }\n  }\n  throw e\n}","preventionTips":["In agent code, construct the move options object with exactly one anchor key.","Omit the unused anchor entirely rather than passing null/undefined.","Validate the XOR condition client-side before the MCP round-trip.","Document the move intent (reorder forward vs backward) by choosing after vs before."],"tags":["mcp","validation","move","arguments"],"backgroundTag":null,"analyzedSha":"0d798ace5828966d9f77f62094d5f7a971ad98f7","analyzedAt":"2026-08-12T17:10:56.221Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}