{"record":{"id":"45f4e7e7d1a45f6e","repo":"vitejs/vite","slug":"circular-worker-imports-detected-vite-does-not-su","errorCode":null,"errorMessage":"Circular worker imports detected. Vite does not support it. Import chain: ${newBundleChain.map((id) => prettifyUrl(id, config.root)).join(' -> ')}","messagePattern":"Circular worker imports detected\\. Vite does not support it\\. Import chain: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/vite/src/node/plugins/worker.ts","lineNumber":178,"sourceCode":"const workerOutputCaches = new WeakMap<ResolvedConfig, WorkerOutputCache>()\n\nasync function bundleWorkerEntry(\n  config: ResolvedConfig,\n  id: string,\n): Promise<WorkerBundle> {\n  const input = cleanUrl(id)\n\n  const workerOutput = workerOutputCaches.get(config.mainConfig || config)!\n  workerOutput.removeBundleIfInvalidated(input)\n\n  const bundleInfo = workerOutput.getWorkerBundle(input)\n  if (bundleInfo) {\n    return bundleInfo\n  }\n\n  const newBundleChain = [...config.bundleChain, input]\n  if (config.bundleChain.includes(input)) {\n    throw new Error(\n      'Circular worker imports detected. Vite does not support it. ' +\n        `Import chain: ${newBundleChain.map((id) => prettifyUrl(id, config.root)).join(' -> ')}`,\n    )\n  }\n\n  // bundle the file as entry to support imports\n  const { rolldown } = await import('rolldown')\n  const { plugins, rolldownOptions, format } = config.worker\n  const workerConfig = await plugins(newBundleChain)\n  const workerEnvironment = new BuildEnvironment('client', workerConfig) // TODO: should this be 'worker'?\n  await workerEnvironment.init()\n\n  const chunkMetadataMap = new ChunkMetadataMap()\n  const workerBuildTarget = workerEnvironment.config.build.target\n  const bundle = await rolldown({\n    ...rolldownOptions,\n    input,\n    plugins: workerEnvironment.plugins.map((p) =>","sourceCodeStart":160,"sourceCodeEnd":196,"githubUrl":"https://github.com/vitejs/vite/blob/b4d66fee14d970f45b8a6f3d7d6aee73ca9b88ab/packages/vite/src/node/plugins/worker.ts#L160-L196","documentation":"bundleWorkerEntry bundles a worker entry with rolldown, threading config.bundleChain to detect cycles. If the worker's import graph leads back to the same worker entry being bundled, Vite throws because recursively bundling a worker into itself is unsupported and would loop forever.","triggerScenarios":"Worker A imports module M which imports Worker A again (or Worker A imports Worker B which imports Worker A). Each bundleWorkerEntry call pushes the input onto bundleChain; a repeat entry triggers the throw.","commonSituations":"Refactoring that made a worker re-import its own entry, circular deps between two worker files, or a barrel file that re-exports a worker entry that itself imports the barrel.","solutions":["Read the printed import chain to find which worker is re-entered, then break that edge.","Extract the shared code both workers use into a third non-worker module that neither worker entry re-imports.","Avoid importing a worker file from another worker file; communicate via postMessage at runtime instead.","Check barrel/index files for accidental re-exports of the worker entry."],"exampleFix":"// before — workerA.ts imports workerB which imports workerA\n// after — move shared logic to shared.ts imported by both\n// workerA.ts: import { work } from './shared'\n// workerB.ts: import { work } from './shared'","handlingStrategy":"validation","validationCode":"// Detect cycles among worker entries before bundling\nfunction hasWorkerCycle(graph, start) {\n  const seen = new Set()\n  function visit(node, stack) {\n    if (stack.has(node)) return true\n    stack.add(node)\n    for (const next of graph[node] ?? []) if (visit(next, stack)) return true\n    stack.delete(node)\n    return seen.has(node) ? false : (seen.add(node), false)\n  }\n  return visit(start, new Set())\n}","typeGuard":null,"tryCatchPattern":"try {\n  return await bundleWorkerEntry(config, id)\n} catch (e) {\n  if (/Circular worker imports/.test(e.message)) {\n    logger.error(`Fix the cycle printed in the error before retrying.`)\n  }\n  throw e\n}","preventionTips":["Keep worker entries isolated; share logic via non-worker modules.","Run a dependency-graph check in CI for worker files.","Avoid barrel files that re-export worker entries."],"tags":["worker","circular-dependency","build","bundling"],"backgroundTag":null,"analyzedSha":"b4d66fee14d970f45b8a6f3d7d6aee73ca9b88ab","analyzedAt":"2026-08-11T11:49:19.515Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}