{"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/d568f8ce3739b532d5bf2c1ee1e45e8a8a473d09/packages/browser/src/client/tester/expect/toMatchScreenshot.ts#L6-L42","documentation":"Thrown by `toMatchScreenshot` at toMatchScreenshot.ts:23-24 when `this.task` or `this.currentTestName` is undefined — i.e. the matcher is invoked outside of an active test scope. The matcher needs the task to record artifacts and the test name to build a stable screenshot filename.","triggerScenarios":"Calling `toMatchScreenshot` from a plain function, inside `beforeAll`/`setup`, at module top level, or inside a Vitest utility invoked outside a test body. Also happens when the matcher is called inside a worker/preview context that never received the test task from the runner.","commonSituations":"Trying to take a baseline screenshot during page setup before any `it()` runs. Calling the matcher inside a custom command helper that is also invoked outside tests. Running the matcher via a manual `expect` invocation in a script.","solutions":["Move the `toMatchScreenshot` call inside an `it()`/`test()` body so the matcher state is populated.","If in a helper, ensure the helper is only called from within a test and that the matcher `this` binding is preserved.","For setup-time screenshots use Playwright/Vitest browser APIs (`page.screenshot()`) instead of the matcher."],"exampleFix":"// before\nbeforeAll(async () => {\n  await page.goto('/')\n  expect(page).toMatchScreenshot('home.png') // no test context\n})\n\n// after\nit('renders home', async () => {\n  await page.goto('/')\n  expect(page).toMatchScreenshot('home.png')\n})","handlingStrategy":"validation","validationCode":"function inTestScope(ctx: { task?: unknown; currentTestName?: string }): boolean {\n  return ctx.task !== undefined && ctx.currentTestName !== undefined\n}\nif (!inTestScope({ task, currentTestName })) throw new Error('toMatchScreenshot must run inside it()/test()')","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Call toMatchScreenshot only inside it()/test() bodies.","Keep matcher helpers on the matcher `this` binding so the test context propagates.","For setup-time screenshots use page.screenshot() rather than the matcher."],"tags":["browser","expect-matcher","tomatchscreenshot","test-context","lifecycle"],"analyzedSha":"d568f8ce3739b532d5bf2c1ee1e45e8a8a473d09","analyzedAt":"2026-08-03T20:23:56.861Z","schemaVersion":2}