{"record":{"id":"6c7b83123737e866","repo":"vitest-dev/vitest","slug":"tomatchscreenshot-cannot-be-used-with-not","errorCode":null,"errorMessage":"'toMatchScreenshot' cannot be used with \"not\"","messagePattern":"'toMatchScreenshot' cannot be used with \"not\"","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/browser/src/client/tester/expect/toMatchScreenshot.ts","lineNumber":20,"sourceCode":"import type { BrowserPage, ScreenshotMatcherOptions } from '../../../../context'\nimport type { ScreenshotMatcherArguments, ScreenshotMatcherOutput } from '../../../shared/screenshotMatcher/types'\nimport type { Locator } from '../locators'\nimport { recordArtifact } from 'vitest'\nimport { getBrowserState } from '../../utils'\nimport { serializeElement } from '../tester-utils'\n\nconst counters = new Map<string, { current: number }>([])\n\nexport default async function toMatchScreenshot(\n  this: MatcherState,\n  actual: BrowserPage | Element | Locator,\n  nameOrOptions?: ScreenshotMatcherOptions | string,\n  options: ScreenshotMatcherOptions = typeof nameOrOptions === 'object'\n    ? nameOrOptions\n    : {},\n): AsyncMatcherResult {\n  if (this.isNot) {\n    throw new Error('\\'toMatchScreenshot\\' cannot be used with \"not\"')\n  }\n\n  if (this.task === undefined || this.currentTestName === undefined) {\n    throw new Error('\\'toMatchScreenshot\\' cannot be used without test context')\n  }\n\n  const counterName = `${this.task.result?.repeatCount ?? 0}${this.testPath}${this.currentTestName}`\n  let counter = counters.get(counterName)\n\n  if (counter === undefined) {\n    counter = { current: 0 }\n\n    counters.set(counterName, counter)\n  }\n\n  counter.current += 1\n\n  const name = typeof nameOrOptions === 'string'","sourceCodeStart":2,"sourceCodeEnd":38,"githubUrl":"https://github.com/vitest-dev/vitest/blob/1fa9837ec26533512fdcad8baebf249771bd340a/packages/browser/src/client/tester/expect/toMatchScreenshot.ts#L2-L38","documentation":"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`.","triggerScenarios":"Any call of the form `expect(page).not.toMatchScreenshot(...)` or `expect(locator).not.toMatchScreenshot(...)`, regardless of options.","commonSituations":"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.","solutions":["Remove the `.not`: use `expect(page).toMatchScreenshot(...)`.","If you need to assert a screenshot does NOT equal a specific baseline, maintain a separate 'negative' baseline file and compare positively against it.","For 'the UI changed' assertions, compare against an updated reference instead of negating."],"exampleFix":"// before\nexpect(page).not.toMatchScreenshot('login')\n\n// after\nexpect(page).toMatchScreenshot('login')","handlingStrategy":"validation","validationCode":"// never negate toMatchScreenshot\nexpect(page).toMatchScreenshot('home') // OK\n// expect(page).not.toMatchScreenshot('home') // would throw","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never use `.not.toMatchScreenshot`.","If a 'changed UI' assertion is needed, maintain a dedicated baseline and compare positively.","Add an ESLint rule or code review check banning negated screenshot matchers."],"tags":["matcher","screenshot","browser","visual-regression"],"backgroundTag":null,"analyzedSha":"1fa9837ec26533512fdcad8baebf249771bd340a","analyzedAt":"2026-08-11T16:11:39.638Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}