{"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/d568f8ce3739b532d5bf2c1ee1e45e8a8a473d09/packages/browser/src/client/tester/context.ts#L297-L333","documentation":"page.screenshot() reads getWorkerState().current and throws if there is no active test. Screenshots must be bound to a test task so Vitest can attribute the image, track repeat counts, and write it to the right path; calling it from module top-level, setup hooks that run outside a test context (rare), or after the test has finished yields no current task.","triggerScenarios":"Calling page.screenshot() at the top level of a test file, inside a beforeAll/beforeEach in certain non-test scopes, or in an async callback that resolves after the test has completed (detached promise). Defined at packages/browser/src/client/tester/context.ts:312-316.","commonSituations":"Taking a baseline screenshot at module load, calling page.screenshot() inside a setTimeout/setInterval callback that outlives the test, or invoking it from a utility invoked outside it()/test().","solutions":["Move the page.screenshot() call inside an it() / test() body.","If it's in a detached async callback, await the callback within the test so it resolves before the test ends.","For setup-time captures, take the screenshot inside the first test or use beforeEach."],"exampleFix":"// before — top-level call, no active test\nawait page.screenshot()\nit('loads home', () => { ... })\n// after\nit('loads home', async () => {\n  await page.screenshot()\n})","handlingStrategy":"validation","validationCode":"import { getWorkerState } from 'vitest'\nconst current = getWorkerState().current\nif (current) {\n  await page.screenshot()\n} else {\n  // not inside a test; skip or move the call\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always call page.screenshot inside it()/test().","Await any async work that calls page.screenshot so it resolves within the test."],"tags":["browser","screenshot","lifecycle","test-context"],"analyzedSha":"d568f8ce3739b532d5bf2c1ee1e45e8a8a473d09","analyzedAt":"2026-08-03T20:23:56.861Z","schemaVersion":2}