{"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/d568f8ce3739b532d5bf2c1ee1e45e8a8a473d09/packages/browser/src/client/tester/expect/toMatchScreenshot.ts#L2-L38","documentation":"Thrown by `toMatchScreenshot` at toMatchScreenshot.ts:19-21 when called with `.not`. Visual regression produces a binary pass/fail plus reference/actual/diff artifacts; negating it has no meaningful semantics and would break the artifact-recording flow, so Vitest explicitly forbids it.","triggerScenarios":"Writing `expect(page).not.toMatchScreenshot('home.png')` or any call where `this.isNot` is true. Triggered before any screenshot is taken, so it fails fast regardless of options.","commonSituations":"Developers reflexively chaining `.not.` to invert every matcher. Migrating from a custom snapshot matcher that allowed negation.","solutions":["Remove the `.not` — express the expected visual state directly in the reference image.","If you need to assert a screenshot does NOT match a specific baseline, maintain a different reference that represents the desired state.","Use `toMatchScreenshot` with options like `diffMethod`/threshold to control tolerance instead of negation."],"exampleFix":"// before\nexpect(page).not.toMatchScreenshot('home.png')\n\n// after\nexpect(page).toMatchScreenshot('home.png')","handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never chain .not. with toMatchScreenshot; visual regression is not negatable.","Express desired visual state via the reference image, not via negation.","Codify the rule in an ESLint custom rule or shared style guide."],"tags":["browser","expect-matcher","tomatchscreenshot","visual-regression","api-misuse"],"analyzedSha":"d568f8ce3739b532d5bf2c1ee1e45e8a8a473d09","analyzedAt":"2026-08-03T20:23:56.861Z","schemaVersion":2}