{"record":{"id":"5e63c7f6985c22a4","repo":"vitest-dev/vitest","slug":"tomatchscreenshot-cannot-be-used-without-test-co","errorCode":null,"errorMessage":"'toMatchScreenshot' cannot be used without test context","messagePattern":"'toMatchScreenshot' cannot be used without test context","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/browser/src/client/tester/expect/toMatchScreenshot.ts","lineNumber":24,"sourceCode":"import { 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'\n    ? nameOrOptions\n    : `${this.currentTestName} ${counter.current}`\n\n  const isPageTarget = isBrowserPage(actual)","sourceCodeStart":6,"sourceCodeEnd":42,"githubUrl":"https://github.com/vitest-dev/vitest/blob/1fa9837ec26533512fdcad8baebf249771bd340a/packages/browser/src/client/tester/expect/toMatchScreenshot.ts#L6-L42","documentation":"Thrown by `toMatchScreenshot` when the matcher's `this` context lacks `this.task` or `this.currentTestName`. The screenshot command needs the running test's identity (to name reference files, attach artifacts, and compute a per-test counter) and the test path; without them it cannot place the captured image. This typically means the matcher was called outside a live Vitest browser test.","triggerScenarios":"Calling `toMatchScreenshot` from a plain script, a Vitest `beforeAll`/global setup that runs outside the test scope, a manually constructed expect context, or any environment where the matcher is invoked without Vitest binding its `MatcherState`.","commonSituations":"Unit-testing the matcher itself in isolation; importing the browser tester entry in Node; calling the matcher inside a `setTimeout`/detached promise after the test finished; running browser matchers under the default Node environment instead of `@vitest/browser`.","solutions":["Ensure the project uses the browser environment: set `// @vitest-environment browser` at the top of the test file or configure `environment: 'browser'`.","Call `toMatchScreenshot` directly inside an `it(...)`/`test(...)` body, not in `beforeAll` or detached callbacks.","If testing the matcher in isolation, construct a full `MatcherState` with `task`, `currentTestName`, and `testPath`, or refactor to invoke it through the real runner."],"exampleFix":"// before (called outside a test, e.g. in a helper module)\nexpect(page).toMatchScreenshot('home')\n\n// after\nimport { test, expect } from 'vitest'\ntest('home renders', () => {\n  expect(page).toMatchScreenshot('home')\n})","handlingStrategy":"validation","validationCode":"// ensure the matcher runs inside a live browser test\nimport { test, expect } from 'vitest'\ntest('visual', () => {\n  expect(page).toMatchScreenshot('home')\n})","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use `// @vitest-environment browser` or set `environment: 'browser'` in config.","Call screenshot matchers only inside `test()`/`it()` bodies.","Avoid invoking matchers from detached promises or setup hooks."],"tags":["matcher","screenshot","browser","test-context"],"backgroundTag":null,"analyzedSha":"1fa9837ec26533512fdcad8baebf249771bd340a","analyzedAt":"2026-08-11T16:11:39.638Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}