vitest-dev/vitest · error · Error

'toMatchScreenshot' cannot be used with "not"

Error message

'toMatchScreenshot' cannot be used with "not"

What it means

Thrown by `toMatchScreenshot` when the matcher is invoked in a negated context, i.e. `expect(...).not.toMatchScreenshot(...)`. Screenshot comparison returns a structured match/mismatch outcome and writes reference/diff artifacts; negating it has no meaningful definition (a 'non-matching screenshot' is not a stable assertion target). The matcher guards this at entry by checking `this.isNot`.

Solutions

  1. Remove the `.not`: use `expect(page).toMatchScreenshot(...)`.
  2. If you need to assert a screenshot does NOT equal a specific baseline, maintain a separate 'negative' baseline file and compare positively against it.
  3. For 'the UI changed' assertions, compare against an updated reference instead of negating.

Example fix

// before
expect(page).not.toMatchScreenshot('login')

// after
expect(page).toMatchScreenshot('login')
Defensive patterns

Strategy: validation

Validate before calling

// never negate toMatchScreenshot
expect(page).toMatchScreenshot('home') // OK
// expect(page).not.toMatchScreenshot('home') // would throw

Prevention

When it happens

Trigger: Any call of the form `expect(page).not.toMatchScreenshot(...)` or `expect(locator).not.toMatchScreenshot(...)`, regardless of options.

Common situations: Copy-pasting a negated `expect(...).not.toMatch(...)` pattern from snapshot tests; misunderstanding the matcher as a generic image-equality assertion; auto-generated test scaffolding that wraps every matcher in `.not` for negative cases.

Related errors


AI-assisted analysis of vitest-dev/vitest@1fa9837ec2 (2026-08-11). Data as JSON: /api/errors/6c7b83123737e866. Report an issue: GitHub.

Appendix: source

Thrown at packages/browser/src/client/tester/expect/toMatchScreenshot.ts:20

import type { BrowserPage, ScreenshotMatcherOptions } from '../../../../context'
import type { ScreenshotMatcherArguments, ScreenshotMatcherOutput } from '../../../shared/screenshotMatcher/types'
import type { Locator } from '../locators'
import { recordArtifact } from 'vitest'
import { getBrowserState } from '../../utils'
import { serializeElement } from '../tester-utils'

const counters = new Map<string, { current: number }>([])

export default async function toMatchScreenshot(
  this: MatcherState,
  actual: BrowserPage | Element | Locator,
  nameOrOptions?: ScreenshotMatcherOptions | string,
  options: ScreenshotMatcherOptions = typeof nameOrOptions === 'object'
    ? nameOrOptions
    : {},
): AsyncMatcherResult {
  if (this.isNot) {
    throw new Error('\'toMatchScreenshot\' cannot be used with "not"')
  }

  if (this.task === undefined || this.currentTestName === undefined) {
    throw new Error('\'toMatchScreenshot\' cannot be used without test context')
  }

  const counterName = `${this.task.result?.repeatCount ?? 0}${this.testPath}${this.currentTestName}`
  let counter = counters.get(counterName)

  if (counter === undefined) {
    counter = { current: 0 }

    counters.set(counterName, counter)
  }

  counter.current += 1

  const name = typeof nameOrOptions === 'string'

View on GitHub (pinned to 1fa9837ec2)