{"record":{"id":"c141002116b3d322","repo":"vitest-dev/vitest","slug":"cannot-take-a-screenshot-outside-of-a-test","errorCode":null,"errorMessage":"Cannot take a screenshot outside of a test.","messagePattern":"Cannot take a screenshot outside of a test\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/browser/src/client/tester/context.ts","lineNumber":315,"sourceCode":"      iframeId: id,\n    } satisfies IframeViewportEvent)\n    return new Promise((resolve, reject) => {\n      channel.addEventListener('message', function handler(e) {\n        if (e.data.event === 'viewport:done' && e.data.iframeId === id) {\n          channel.removeEventListener('message', handler)\n          resolve()\n        }\n        if (e.data.event === 'viewport:fail' && e.data.iframeId === id) {\n          channel.removeEventListener('message', handler)\n          reject(new Error(e.data.error))\n        }\n      })\n    })\n  },\n  async screenshot(options = {}) {\n    const currentTest = getWorkerState().current\n    if (!currentTest) {\n      throw new Error('Cannot take a screenshot outside of a test.')\n    }\n\n    if (currentTest.concurrent) {\n      throw new Error(\n        'Cannot take a screenshot in a concurrent test because '\n        + 'concurrent tests run at the same time in the same iframe and affect each other\\'s environment. '\n        + 'Use a non-concurrent test to take a screenshot.',\n      )\n    }\n\n    const repeatCount = currentTest.result?.repeatCount ?? 0\n    const taskName = getTaskFullName(currentTest)\n    const number = screenshotIds[repeatCount]?.[taskName] ?? 1\n\n    screenshotIds[repeatCount] ??= {}\n    screenshotIds[repeatCount][taskName] = number + 1\n\n    const name","sourceCodeStart":297,"sourceCodeEnd":333,"githubUrl":"https://github.com/vitest-dev/vitest/blob/1fa9837ec26533512fdcad8baebf249771bd340a/packages/browser/src/client/tester/context.ts#L297-L333","documentation":"page.screenshot() reads the current test from the worker state; if there is no current test (because screenshot is invoked outside the test function body, e.g. at module top-level, in a beforeEach/beforeAll hook, or after the test has finished), Vitest throws. Screenshots are bound to a task for naming and attachment, so they require an active test context.","triggerScenarios":"Calling page.screenshot() at the top level of a spec file; calling it inside beforeAll/beforeEach/afterEach/afterAll; calling it after an await that outlives the test (e.g. setTimeout callback); calling it during module import or in a helper invoked outside a test.","commonSituations":"Taking screenshots for debugging in a setup hook; refactoring that moved the screenshot call out of the test body; race conditions where an async callback fires after the test completed; helper utilities that assume they are always called from a test.","solutions":["Move the page.screenshot() call inside the body of an it/test function.","If you need a screenshot during setup, capture the DOM state with prettyDOM() instead, or restructure so the screenshot runs inside a test.","Ensure no setTimeout/setInterval or detached promise triggers the screenshot after the test ends."],"exampleFix":"// before\nbeforeAll(async () => { await page.screenshot() })\n// after\nit('renders', async () => { await page.screenshot() })","handlingStrategy":"validation","validationCode":"import { getWorkerState } from 'vitest'\nif (!getWorkerState().current) {\n  // skip screenshot — not inside a test\n} else {\n  await page.screenshot()\n}","typeGuard":"function insideTest(): boolean {\n  return !!getWorkerState().current\n}","tryCatchPattern":null,"preventionTips":["Keep page.screenshot() calls inside the body of it/test only.","Audit helpers that screenshot to ensure they are always called from a test.","Avoid setTimeout/setInterval callbacks that outlive the test."],"tags":["browser","screenshot","test-lifecycle","worker-state"],"backgroundTag":null,"analyzedSha":"1fa9837ec26533512fdcad8baebf249771bd340a","analyzedAt":"2026-08-11T16:11:39.638Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}