vitest-dev/vitest · error · Error
[vitest] `importScripts` is not supported in Vite workers. P
Error message
[vitest] `importScripts` is not supported in Vite workers. Please, consider using `import` instead.
What it means
Vitest's web worker implementation (packages/web-worker/src/runner.ts:17-18, 39-42) is module-based: worker code is executed through Vite's module runner, not the legacy synchronous script loader. To mimic the global API surface, startWebWorkerModuleRunner injects a stub `importScripts` into the worker's compiled-function scope, but that stub unconditionally throws this Error. Any call to importScripts() inside worker code under @vitest/web-worker therefore fails immediately rather than silently doing nothing.
Source
Thrown at packages/web-worker/src/runner.ts:40
const evaluator = new VitestModuleEvaluator(vm, {
interopDefault: state.config.deps.interopDefault,
injectCjsGlobals: state.config.injectCjsGlobals,
moduleExecutionInfo: state.moduleExecutionInfo,
getCurrentTestFilepath: () => state.filepath,
compiledFunctionArgumentsNames,
compiledFunctionArgumentsValues,
})
return startVitestModuleRunner({
evaluator,
evaluatedModules: state.evaluatedModules,
mocker,
state,
})
}
function importScripts() {
throw new Error(
'[vitest] `importScripts` is not supported in Vite workers. Please, consider using `import` instead.',
)
}
View on GitHub (pinned to d568f8ce37)
Solutions
- Replace `importScripts('./x.js')` with a static or dynamic ES module import: `import './x.js'` or `await import('./x.js')`.
- If the importScripts call lives in a third-party dependency, load that dependency through Vite's module graph instead of a raw script URL, or alias/virtualize it so its worker entry uses ESM.
- Make the worker a module worker in production too (`new Worker(url, { type: 'module' })`) so the same source works in both Vitest and the browser without importScripts.
- Guard the call if it must remain conditional: `if (typeof importScripts === 'function' && !importScripts.__vitest) importScripts(...)` — though the clean fix is migrating to ESM.
Example fix
// before — inside worker.js (classic worker API)
self.importScripts('./polyfill.js')
self.importScripts('https://cdn.example/lib.js')
// after — ES module imports, works under @vitest/web-worker
import './polyfill.js'
// for runtime-determined URLs, use dynamic import
const mod = await import(/* @vite-ignore */ 'https://cdn.example/lib.js') Defensive patterns
Strategy: validation
Validate before calling
// Reject worker source files that use importScripts before running them.
// Apply in a custom plugin or a pre-test check on the worker entry source.
function usesImportScripts(source) {
// crude but effective: catches the common global and self. forms
return /(^|[^\w.$])\b(importScripts)\s*\(/.test(source)
}
function assertWorkerIsModuleBased(workerSource) {
if (usesImportScripts(workerSource)) {
throw new Error(
'Worker source uses importScripts(), which @vitest/web-worker does not support. ' +
'Convert to static/dynamic ES module imports.',
)
}
}
// const src = readFileSync('./src/worker.js', 'utf8')
// assertWorkerIsModuleBased(src) Try / catch
// If you must keep a legacy branch, contain the failure and migrate.
try {
// legacy path that may call importScripts
loadClassicWorkerSupport()
} catch (error) {
if (/importScripts is not supported/i.test(error.message)) {
console.warn('Falling back to ESM worker entry')
await import('./worker.js')
} else {
throw error
}
} Prevention
- Author workers as module workers (`new Worker(url, { type: 'module' })`) in production so the same source runs under Vitest unchanged.
- Avoid importScripts even in conditionals — gate on whether you are in a Vitest worker, not on whether importScripts exists.
- Lint worker sources for `importScripts(` with a custom ESLint rule so the call never lands in CI.
When it happens
Trigger: Worker source code (the file passed to `new Worker(new URL('./w.js', import.meta.url))`) calling `importScripts('./lib.js')`, `importScripts(url1, url2)`, or any code path that reaches the global `importScripts` inside a Vitest web worker. Also triggered by third-party libraries that detect a worker context and fall back to importScripts().
Common situations: Porting a real web worker (classic worker, not module worker) into Vitest tests; using a library that uses importScripts to load a UMD/script bundle inside a worker; sharing worker code between a classic-worker production build and the Vitest test environment; upgrading from an environment that silently ignored importScripts.
Related errors
- Cannot parse the module format of '${url}' because "module.f
- Cannot spy on export "${String(key)}". Module namespace is n
- require() is not supported in virtual modules. Trying to cal
- createNodeImportMeta is not supported in this version of Vit
- Runner must export a default function, but got ${typeof mod.
AI-assisted analysis of vitest-dev/vitest@d568f8ce37 (2026-08-03).
Data as JSON: /data/errors/d33d5e644c8abaae.json.
Report an issue: GitHub.