{"record":{"id":"711043cb8d5ef459","repo":"microsoft/playwright","slug":"not-matcher-requires-expected-result","errorCode":null,"errorMessage":"\"not\" matcher requires expected result","messagePattern":"\"not\" matcher requires expected result","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/playwright-core/src/server/page.ts","lineNumber":733,"sourceCode":"    const locator = options.locator;\n    const rafrafScreenshot = locator ? async (progress: Progress, timeout: number) => {\n      return await locator.frame.rafrafTimeoutScreenshotElementWithProgress(progress, locator.selector, timeout, options || {});\n    } : async (progress: Progress, timeout: number) => {\n      await this.performActionPreChecks(progress);\n      await this.mainFrame().rafrafTimeout(progress, timeout);\n      return await this.screenshotter.screenshotPage(progress, options || {});\n    };\n\n    let intermediateResult: {\n      actual?: Buffer,\n      previous?: Buffer,\n      errorMessage: string,\n      diff?: Buffer,\n    } | undefined;\n\n    try {\n      if (!options.expected && options.isNot)\n        throw new Error('\"not\" matcher requires expected result');\n      const format = validateScreenshotOptions(options || {});\n      const comparator = getComparator(`image/${format}`);\n      const areEqualScreenshots = (actual: Buffer | undefined, expected: Buffer | undefined, previous: Buffer | undefined) => {\n        const comparatorResult = actual && expected ? comparator(actual, expected, options) : undefined;\n        if (comparatorResult !== undefined && !!comparatorResult === !!options.isNot)\n          return true;\n        if (comparatorResult)\n          intermediateResult = { errorMessage: comparatorResult.errorMessage, diff: comparatorResult.diff, actual, previous };\n        return false;\n      };\n      let actual: Buffer | undefined;\n      let previous: Buffer | undefined;\n      const pollIntervals = [0, 100, 250, 500];\n      if (options.expected)\n        progress.log(`  verifying given screenshot expectation`);\n      else\n        progress.log(`  generating new stable screenshot expectation`);\n      let isFirstIteration = true;","sourceCodeStart":715,"sourceCodeEnd":751,"githubUrl":"https://github.com/microsoft/playwright/blob/c8fc3bf8d31542d59b4d4d9eaab1df93ff541dc6/packages/playwright-core/src/server/page.ts#L715-L751","documentation":"Thrown by the screenshot expectation engine (used by expect(page).toHaveScreenshot()) when the matcher is negated (.not) but no expected/baseline image was supplied. Negation requires an existing reference to compare against; without one, Playwright cannot decide what 'does not match' means, so it refuses rather than auto-creating a baseline under a negation.","triggerScenarios":"Using expect(page).not.toHaveScreenshot() before any baseline has been generated; referencing a snapshot name whose expected file was deleted or never committed; running .not.toHaveScreenshot on a fresh project with an empty snapshot directory.","commonSituations":"First test run before baselines exist; CI on a clean checkout where snapshot artifacts are gitignored; a typo in the snapshot name causing Playwright to look for a non-existent expectation.","solutions":["Run the assertion without .not once to generate the baseline (expect(page).toHaveScreenshot('name.png')), commit the snapshot, then re-add .not.","Verify the snapshot name matches an existing file in the snapshots directory and that snapshots are committed to the repo.","If you genuinely want 'no screenshot matches X', supply an explicit expected buffer via the lower-level API rather than relying on auto-baseline under negation."],"exampleFix":"// before\nawait expect(page).not.toHaveScreenshot('home.png'); // no baseline yet -> throws\n// after (generate baseline first)\nawait expect(page).toHaveScreenshot('home.png'); // run once, commit snapshot\nawait expect(page).not.toHaveScreenshot('home.png'); // now valid","handlingStrategy":"validation","validationCode":"// Ensure a baseline exists before using .not\nimport { existsSync } from 'node:fs';\nimport path from 'node:path';\nfunction hasBaseline(testDir, name) {\n  return existsSync(path.join(testDir, '-snapshots', name));\n}\n// only negate when a baseline file is present\nconst negate = hasBaseline(__dirname, 'home-chromium.png') ? '.not' : '';","typeGuard":null,"tryCatchPattern":"try {\n  await expect(page).not.toHaveScreenshot('home.png');\n} catch (e) {\n  if (/\"not\" matcher requires expected result/.test(e.message))\n    throw new Error('No baseline for negated screenshot; run toHaveScreenshot once to generate it');\n  throw e;\n}","preventionTips":["Generate baselines on a clean run and commit snapshot artifacts.","Do not use .not.toHaveScreenshot until a baseline file exists.","Keep snapshot names stable and consistent across platforms."],"tags":["screenshot","tohavescreenshot","matcher","expect","baseline"],"backgroundTag":null,"analyzedSha":"c8fc3bf8d31542d59b4d4d9eaab1df93ff541dc6","analyzedAt":"2026-08-12T07:26:36.950Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}