vitest-dev/vitest · error · Error
Cannot take a screenshot in a concurrent test because…
Error message
Cannot take a screenshot in a concurrent test because concurrent tests run at the same time in the same iframe and affect each other's environment. Use a non-concurrent test to take a screenshot.
What it means
Concurrent tests in Vitest browser mode share the same iframe, so a screenshot would capture an interleaved DOM from sibling tests. Vitest forbids screenshots in tests marked .concurrent to prevent misleading artifacts. The guard sits at the top of page.screenshot() right after the current-test check.
Solutions
- Remove .concurrent from the specific test that needs a screenshot (or its describe block).
- Keep concurrency for fast assertions but isolate the visual test by splitting it into a separate non-concurrent suite.
- Replace the screenshot with a DOM assertion (e.g. toMatchAriaSnapshot) which is safe under concurrency.
Example fix
// before
it.concurrent('shows chart', async () => { await page.screenshot() })
// after
it('shows chart', async () => { await page.screenshot() }) Defensive patterns
Strategy: validation
Validate before calling
import { getWorkerState } from 'vitest'
const t = getWorkerState().current
if (t?.concurrent) {
// do not screenshot in concurrent tests
} else {
await page.screenshot()
} Type guard
function canScreenshot(): boolean {
const t = getWorkerState().current
return !!t && !t.concurrent
} Prevention
- Do not mark screenshot tests as .concurrent.
- Isolate visual tests into their own non-concurrent suite.
- Prefer toMatchAriaSnapshot when running concurrent suites.
When it happens
Trigger: Declaring a test as it.concurrent('...', ...) (or it.concurrent.only) and calling page.screenshot() inside it; enabling test.concurrent at the suite/describe level; importing a helper that screenshots while the suite is configured concurrent.
Common situations: Enabling concurrent mode globally to speed up the suite; copy-pasting a screenshot helper into a concurrent suite; running with --no-isolate or concurrent config defaults.
Related errors
- Cannot compare screenshots without a test path
- Cannot take a screenshot outside of a test.
- Cannot take a screenshot without a test path
- Couldn't write file to fs
- No codec found for type
AI-assisted analysis of vitest-dev/vitest@1fa9837ec2 (2026-08-11).
Data as JSON: /api/errors/f0f19bf4746d388b.
Report an issue: GitHub.
Appendix: source
Thrown at packages/browser/src/client/tester/context.ts:319
if (e.data.event === 'viewport:done' && e.data.iframeId === id) {
channel.removeEventListener('message', handler)
resolve()
}
if (e.data.event === 'viewport:fail' && e.data.iframeId === id) {
channel.removeEventListener('message', handler)
reject(new Error(e.data.error))
}
})
})
},
async screenshot(options = {}) {
const currentTest = getWorkerState().current
if (!currentTest) {
throw new Error('Cannot take a screenshot outside of a test.')
}
if (currentTest.concurrent) {
throw new Error(
'Cannot take a screenshot in a concurrent test because '
+ 'concurrent tests run at the same time in the same iframe and affect each other\'s environment. '
+ 'Use a non-concurrent test to take a screenshot.',
)
}
const repeatCount = currentTest.result?.repeatCount ?? 0
const taskName = getTaskFullName(currentTest)
const number = screenshotIds[repeatCount]?.[taskName] ?? 1
screenshotIds[repeatCount] ??= {}
screenshotIds[repeatCount][taskName] = number + 1
const name
= options.path || `${taskName.replace(/[^a-z0-9]/gi, '-')}-${number}.png`
const [element, ...mask] = await Promise.all([
options.element ? serializeElement(options.element, options) : undefined,View on GitHub (pinned to 1fa9837ec2)