slidevjs/slidev · error · Error

The `before`/`after` anchor must be a different slide than `

Error message

The `before`/`after` anchor must be a different slide than `from`.

What it means

Thrown by moveSlide when anchorNo === from, i.e. the caller asked to move a slide before/after itself, which is a no-op and would produce an inconsistent splice. Caught before any file mutation.

Source

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

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)
    assertNotEntryHeadmatter(data, anchor.source, 'insert a slide before')

  const md = getMarkdown(data, slide.source)
  const fromIdx = md.slides.indexOf(slide.source)

View on GitHub (pinned to 0d798ace58)

Solutions

  1. Choose an anchor slide number different from from.
  2. If the intent is to leave the slide in place, skip the moveSlide call entirely.

Example fix

// before: anchor equals source
await tools['slidev-move-slide']({ from: 3, after: 3 }) // throws

// after: pick a distinct anchor
await tools['slidev-move-slide']({ from: 3, after: 4 })
Defensive patterns

Strategy: validation

Validate before calling

function anchorDistinct(from: number, anchor?: number): boolean {
  return anchor != null && anchor !== from
}

// before moveSlide:
const anchorNo = before ?? after
if (!anchorDistinct(from, anchorNo)) {
  throw new Error('Anchor must differ from `from`.')
}

Type guard

function isValidMove(
  o: { from: number; before?: number; after?: number },
): o is { from: number; before: number } | { from: number; after: number } {
  const anchor = o.before ?? o.after
  return anchor != null && anchor !== o.from
}

Try / catch

try {
  await moveSlide(data, { from, before, after })
} catch (e) {
  if (e instanceof Error && /anchor must be a different slide/.test(e.message)) {
    return { error: 'No-op move: anchor equals source.' }
  }
  throw e
}

Prevention

When it happens

Trigger: Calling slidev-move-slide with before or after equal to from (e.g. move slide 3 before slide 3).

Common situations: A caller computes the anchor from the source position by mistake; an agent loops over candidate positions and accidentally passes the source's own number.

Related errors


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