vitest-dev/vitest · error · Error
[@vitest/web-worker] Cannot initiate a custom Web Worker.
Error message
[@vitest/web-worker] Cannot initiate a custom Web Worker. "${name}" is not supported in this environment. Please, consider using jsdom or happy-dom environment. What it means
assertGlobalExists guards the custom Worker constructor: @vitest/web-worker needs browser globals (such as Worker, MessageChannel, structuredClone) to exist on globalThis. In a bare Node test environment those globals are absent, so the helper throws this error at construction time, before any worker code runs, and points to jsdom or happy-dom as the fix.
Solutions
- Switch the Vitest environment to a DOM provider: set environment: 'jsdom' (or 'happy-dom') in the config, or pass --environment happy-dom.
- Install the environment package: npm i -D jsdom (or happy-dom).
- Scope it per file with a comment directive at the top of the test: // @vitest-environment happy-dom.
Example fix
// before // @vitest-environment node new MyWorker(url) // throws // after // @vitest-environment happy-dom new MyWorker(url)
Defensive patterns
Strategy: validation
Validate before calling
function environmentSupportsWorker() {
return typeof globalThis !== 'undefined'
&& 'Worker' in globalThis
}
if (!environmentSupportsWorker()) {
throw new Error('Current Vitest environment lacks Worker; set environment to jsdom or happy-dom.')
} Type guard
function hasWorkerGlobal(g: typeof globalThis): g is typeof globalThis & { Worker: typeof Worker } {
return typeof g !== 'undefined' && 'Worker' in g
} Try / catch
try {
const worker = new CustomWorker(url)
} catch (e) {
if (e instanceof Error && /not supported in this environment/.test(e.message)) {
console.warn('Skipping worker test: set // @vitest-environment happy-dom')
return
}
throw e
} Prevention
- Pin the environment in vitest.config (environment: 'happy-dom') for any project using web workers.
- Add a // @vitest-environment directive to files that instantiate workers.
- Install the environment shim package (jsdom or happy-dom) as a dev dependency.
- Guard worker-instantiating tests with an environmentSupportsWorker() check so they skip cleanly under node.
When it happens
Trigger: Instantiating a Worker through the @vitest/web-worker constructor while the Vitest environment is node (no DOM shim). The check runs synchronously during Worker construction, via assertGlobalExists called with the missing global name.
Common situations: Default environment left as node; forgot to set jsdom or happy-dom; an environment shim package is missing or an incompatible version that does not define the required global; an SSR-style test that imports worker code incidentally.
Related errors
- aria adapter expects an Element
- Cannot find environment for
- cannot read when saving inline snapshot
- Cannot use the `bench` test-context fixture within a…
- Element not found
AI-assisted analysis of vitest-dev/vitest@1fa9837ec2 (2026-08-11).
Data as JSON: /api/errors/1e58dce6ca900be2.
Report an issue: GitHub.
Appendix: source
Thrown at packages/web-worker/src/utils.ts:10
import type { Debugger } from 'obug'
import type { CloneOption } from './types'
import ponyfillStructuredClone from '@ungap/structured-clone'
import { createDebug } from 'obug'
export const debug: Debugger = createDebug('vitest:web-worker')
export function assertGlobalExists(name: string): void {
if (!(name in globalThis)) {
throw new Error(
`[@vitest/web-worker] Cannot initiate a custom Web Worker. "${name}" is not supported in this environment. Please, consider using jsdom or happy-dom environment.`,
)
}
}
function createClonedMessageEvent(
data: any,
transferOrOptions: StructuredSerializeOptions | Transferable[] | undefined,
clone: CloneOption,
) {
const transfer = Array.isArray(transferOrOptions)
? transferOrOptions
: transferOrOptions?.transfer
debug('clone worker message %o', data)
const origin = typeof location === 'undefined' ? undefined : location.origin
const ports = transfer?.filter((t): t is MessagePort => t instanceof MessagePort)
View on GitHub (pinned to 1fa9837ec2)