vitest-dev/vitest · error · Error

Cannot take a screenshot in a concurrent test because concur

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

page.screenshot() refuses to run when the active test is marked concurrent (currentTest.concurrent === true). Concurrent browser tests share the same iframe DOM, so a screenshot from one would capture state mutated by sibling tests, producing flaky/misleading images. Defined at packages/browser/src/client/tester/context.ts:318-324.

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 d568f8ce37)

Solutions

  1. Remove .concurrent from the test that needs a screenshot, or split the screenshot into a separate non-concurrent test.
  2. If concurrency is set globally via sequence.concurrent: true, mark the screenshot test with it.sequentialOnly / it.not.concurrent.
  3. Reorganize: run assertion-heavy tests concurrently and screenshot tests in a sequential describe block.

Example fix

// before
it.concurrent('renders', async () => {
  await page.screenshot()
})
// after
it('renders', async () => {
  await page.screenshot()
})
Defensive patterns

Strategy: validation

Validate before calling

import { getWorkerState } from 'vitest'
const current = getWorkerState().current
if (current && !current.concurrent) {
  await page.screenshot()
}

Prevention

When it happens

Trigger: Declaring a test with it.concurrent(...) or test.concurrent(...) and then calling page.screenshot() inside its body.

Common situations: Enabling concurrency for speed in browser suites, then adding visual regression screenshots; copying a concurrent test pattern from node tests into browser tests.

Related errors


AI-assisted analysis of vitest-dev/vitest@d568f8ce37 (2026-08-03). Data as JSON: /data/errors/f0f19bf4746d388b.json. Report an issue: GitHub.