{"record":{"id":"2fec3b4ccbe5cee8","repo":"vitest-dev/vitest","slug":"cannot-take-a-screenshot-without-a-test-path","errorCode":null,"errorMessage":"Cannot take a screenshot without a test path","messagePattern":"Cannot take a screenshot without a test path","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/browser-playwright/src/commands/screenshot.ts","lineNumber":38,"sourceCode":"    transform: none !important;\n  }\n`\n\n/**\n * Takes a screenshot using the provided browser context and returns a buffer and the expected screenshot path.\n *\n * **Note**: the returned `path` indicates where the screenshot *might* be found.\n * It is not guaranteed to exist, especially if `options.save` is `false`.\n *\n * @throws {Error} If the function is not called within a test or if the browser provider does not support screenshots.\n */\nexport async function takeScreenshot(\n  context: BrowserCommandContext,\n  name: string,\n  options: Omit<ScreenshotCommandOptions, 'base64'>,\n): Promise<{ buffer: Buffer<ArrayBufferLike>; path: string }> {\n  if (!context.testPath) {\n    throw new Error(`Cannot take a screenshot without a test path`)\n  }\n\n  const path = resolveScreenshotPath(\n    context.testPath,\n    name,\n    context.project.config,\n    options.path,\n  )\n\n  // playwright does not need a screenshot path if we don't intend to save it\n  let savePath: string | undefined\n\n  if (options.save) {\n    savePath = normalize(path)\n\n    assertBrowserApiWrite(context.project, savePath)\n    assertBrowserFileAccess(context.project, savePath)\n","sourceCodeStart":20,"sourceCodeEnd":56,"githubUrl":"https://github.com/vitest-dev/vitest/blob/1fa9837ec26533512fdcad8baebf249771bd340a/packages/browser-playwright/src/commands/screenshot.ts#L20-L56","documentation":"Vitest's browser screenshot command (takeScreenshot) resolves the output path from the running test file. It requires context.testPath to compute where to save the screenshot. Without a bound test file there is no deterministic location, so the command refuses to run. This is the entry behind page.screenshot(), expect(element).toMatchScreenshot(), and the expect(page).toMatchSnapshot() flow when targeting the browser.","triggerScenarios":"Calling page.screenshot() / expect(locator).toMatchScreenshot() from outside an `it`/`test` callback (e.g. module top-level, beforeAll/beforeEach that runs without testPath, a plain script importing vitest/browser, or a custom browser command invoked without a test in scope). Also when a screenshot is triggered during global teardown where BrowserCommandContext.testPath is undefined.","commonSituations":"Running browser tests with a pool that does not set testPath; invoking screenshot logic from a helper imported by both browser and non-browser specs; misconfigured project where browser tests accidentally run under the `forks`/`threads` pool; calling takeScreenshot via a registered browser command at a time vitest has not yet entered a test.","solutions":["Move the screenshot call inside an `it('...', async () => { ... })` body so a testPath is bound.","Verify `test.browser` project is using `pool: 'browser'` and the file matches `test.include` for the browser project, not a node project.","If invoking from a custom browser command, only call it when `context.testPath` is defined; guard with `if (!context.testPath) return`.","Ensure the test file is not imported by a non-browser runner (e.g. eslint, typecheck, or a node test config) that would execute it without testPath."],"exampleFix":"// before\nimport { page } from 'vitest/browser'\npage.screenshot() // at module top-level -> throws\n\n// after\nimport { test, expect } from 'vitest'\nimport { page } from 'vitest/browser'\ntest('renders', async () => {\n  await expect(page).toHaveScreenshot()\n})","handlingStrategy":"validation","validationCode":"import type { BrowserCommandContext } from 'vitest/node'\n\nfunction assertInTest(ctx: BrowserCommandContext): asserts ctx is BrowserCommandContext & { testPath: string } {\n  if (!ctx.testPath) {\n    throw new Error('page.screenshot() must be called inside an it()/test() block')\n  }\n}\n\n// before screenshotting:\nassertInTest(context)","typeGuard":"function hasTestPath(ctx: { testPath?: string }): ctx is { testPath: string } {\n  return typeof ctx.testPath === 'string' && ctx.testPath.length > 0\n}","tryCatchPattern":null,"preventionTips":["Only call page.screenshot()/toMatchScreenshot() inside an `it`/`test` body.","Keep browser specs in a dedicated project with `pool: 'browser'` so testPath is always set.","Do not import screenshot helpers from setup files that may run without a test."],"tags":["browser","screenshot","playwright","lifecycle"],"backgroundTag":null,"analyzedSha":"1fa9837ec26533512fdcad8baebf249771bd340a","analyzedAt":"2026-08-11T16:11:39.638Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}