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

  1. Replace `importScripts('./x.js')` with a static or dynamic ES module import: `import './x.js'` or `await import('./x.js')`.
  2. 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.
  3. 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.
  4. 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

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


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