slidevjs/slidev · error · Error

Specify exactly one of `before` or `after`.

Error message

Specify exactly one of `before` or `after`.

What it means

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.

Source

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

  before?: number
  /** Move the slide right after this rendered slide number */
  after?: number
}

export interface MoveSlideResult {
  moved: SlideInfo
  anchor: SlideInfo
  filepath: string
  fileContent: string
}

/**
 * Move a slide before or after another slide within the same markdown file.
 */
export async function moveSlide(data: LoadedSlidevData, options: MoveSlideOptions): Promise<MoveSlideResult> {
  const { from, before, after } = options
  if ((before == null) === (after == null))
    throw new Error('Specify exactly one of `before` or `after`.')

  const anchorNo = (before ?? after)!
  if (anchorNo === from)
    throw new Error('The `before`/`after` anchor must be a different slide than `from`.')

  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)

View on GitHub (pinned to 0d798ace58)

Solutions

  1. Provide exactly one of before (move to just before that slide) or after (move to just after that slide).
  2. If you only have a target position, compute one anchor and omit the other entirely (do not pass null).

Example fix

// before: ambiguous - both anchors
await tools['slidev-move-slide']({ from: 2, before: 5, after: 5 }) // throws

// after: exactly one anchor
await tools['slidev-move-slide']({ from: 2, before: 5 })
Defensive patterns

Strategy: validation

Validate before calling

function exactlyOneAnchor(opts: { before?: number; after?: number }): boolean {
  return (opts.before != null) !== (opts.after != null)
}

// before moveSlide:
if (!exactlyOneAnchor({ before, after })) {
  throw new Error('Pass exactly one of `before` or `after`.')
}

Type guard

function hasSingleAnchor(o: unknown): o is { before?: number; after?: number } {
  if (!o || typeof o !== 'object') return false
  const { before, after } = o as any
  return (before != null) !== (after != null)
}

Try / catch

try {
  await moveSlide(data, { from, before, after })
} catch (e) {
  if (e instanceof Error && e.message === 'Specify exactly one of `before` or `after`.') {
    // pick a sensible default anchor and retry, or prompt the caller
    return { error: 'Ambiguous move: provide exactly one of before/after.' }
  }
  throw e
}

Prevention

When it happens

Trigger: Calling slidev-move-slide (or moveSlide) with both before and after set, or with both omitted.

Common situations: 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.

Related errors


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