{"id":"d33d5e644c8abaae","repo":"vitest-dev/vitest","slug":"vitest-importscripts-is-not-supported-in-vite","errorCode":null,"errorMessage":"[vitest] `importScripts` is not supported in Vite workers. Please, consider using `import` instead.","messagePattern":"\\[vitest\\] `importScripts` is not supported in Vite workers\\. Please, consider using `import` instead\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/web-worker/src/runner.ts","lineNumber":40,"sourceCode":"  const evaluator = new VitestModuleEvaluator(vm, {\n    interopDefault: state.config.deps.interopDefault,\n    injectCjsGlobals: state.config.injectCjsGlobals,\n    moduleExecutionInfo: state.moduleExecutionInfo,\n    getCurrentTestFilepath: () => state.filepath,\n    compiledFunctionArgumentsNames,\n    compiledFunctionArgumentsValues,\n  })\n\n  return startVitestModuleRunner({\n    evaluator,\n    evaluatedModules: state.evaluatedModules,\n    mocker,\n    state,\n  })\n}\n\nfunction importScripts() {\n  throw new Error(\n    '[vitest] `importScripts` is not supported in Vite workers. Please, consider using `import` instead.',\n  )\n}\n","sourceCodeStart":22,"sourceCodeEnd":44,"githubUrl":"https://github.com/vitest-dev/vitest/blob/d568f8ce3739b532d5bf2c1ee1e45e8a8a473d09/packages/web-worker/src/runner.ts#L22-L44","documentation":"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.","triggerScenarios":"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().","commonSituations":"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.","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."],"exampleFix":"// before — inside worker.js (classic worker API)\nself.importScripts('./polyfill.js')\nself.importScripts('https://cdn.example/lib.js')\n\n// after — ES module imports, works under @vitest/web-worker\nimport './polyfill.js'\n// for runtime-determined URLs, use dynamic import\nconst mod = await import(/* @vite-ignore */ 'https://cdn.example/lib.js')","handlingStrategy":"validation","validationCode":"// Reject worker source files that use importScripts before running them.\n// Apply in a custom plugin or a pre-test check on the worker entry source.\nfunction usesImportScripts(source) {\n  // crude but effective: catches the common global and self. forms\n  return /(^|[^\\w.$])\\b(importScripts)\\s*\\(/.test(source)\n}\n\nfunction assertWorkerIsModuleBased(workerSource) {\n  if (usesImportScripts(workerSource)) {\n    throw new Error(\n      'Worker source uses importScripts(), which @vitest/web-worker does not support. ' +\n        'Convert to static/dynamic ES module imports.',\n    )\n  }\n}\n// const src = readFileSync('./src/worker.js', 'utf8')\n// assertWorkerIsModuleBased(src)","typeGuard":null,"tryCatchPattern":"// If you must keep a legacy branch, contain the failure and migrate.\ntry {\n  // legacy path that may call importScripts\n  loadClassicWorkerSupport()\n} catch (error) {\n  if (/importScripts is not supported/i.test(error.message)) {\n    console.warn('Falling back to ESM worker entry')\n    await import('./worker.js')\n  } else {\n    throw error\n  }\n}","preventionTips":["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."],"tags":["web-worker","esm","importscripts","module-runner"],"analyzedSha":"d568f8ce3739b532d5bf2c1ee1e45e8a8a473d09","analyzedAt":"2026-08-03T20:23:56.861Z","schemaVersion":2}