{"id":"1c5beba084592d9e","repo":"vitest-dev/vitest","slug":"the-worker-thread-was-torn-down-or-never-initializ","errorCode":null,"errorMessage":"The worker thread was torn down or never initialized. This is a bug in Vitest.","messagePattern":"The worker thread was torn down or never initialized\\. This is a bug in Vitest\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/vitest/src/node/pools/workers/threadsWorker.ts","lineNumber":74,"sourceCode":"  async stop(): Promise<void> {\n    await this.thread.terminate()\n\n    this._thread?.stdout?.unpipe(this.stdout)\n    this.stdout.setMaxListeners(this.stdout.getMaxListeners() - 1)\n\n    this._thread?.stderr?.unpipe(this.stderr)\n    this.stderr.setMaxListeners(this.stderr.getMaxListeners() - 1)\n\n    this._thread = undefined\n  }\n\n  deserialize(data: unknown): unknown {\n    return data\n  }\n\n  private get thread() {\n    if (!this._thread) {\n      throw new Error(`The worker thread was torn down or never initialized. This is a bug in Vitest.`)\n    }\n    return this._thread\n  }\n}\n","sourceCodeStart":56,"sourceCodeEnd":79,"githubUrl":"https://github.com/vitest-dev/vitest/blob/d568f8ce3739b532d5bf2c1ee1e45e8a8a473d09/packages/vitest/src/node/pools/workers/threadsWorker.ts#L56-L79","documentation":"Internal assertion in the threads worker: the private _thread getter throws if the underlying Worker was never created (start() not called or failed) or was cleared (set to undefined after stop()). Used by on/off/send, so interacting with a torn-down worker thread trips it.","triggerScenarios":"ThreadsPoolWorker.on/off/send is called when this._thread is undefined — before start() or after stop() set it to undefined at packages/vitest/src/node/pools/workers/threadsWorker.ts:65-74. Same shape as the forks worker: a message posted to a stopped worker.","commonSituations":"Teardown/cancellation race where PoolRunner.postMessage runs after the thread was terminated; a regression in the STOPPED-state message gating; experimental API misuse sending after stop().","solutions":["Report as a Vitest bug with reproduction (cancellation/teardown focus).","Retry on transient Ctrl+C races.","If using the @experimental ThreadsPoolWorker directly, never interact with the worker after stop()."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  await vitest.start()\n} catch (e) {\n  if (e.message === 'The worker thread was torn down or never initialized. This is a bug in Vitest.') {\n    console.error('Threads worker teardown race — retry; if persistent, report as a bug.')\n  }\n  throw e\n}","preventionTips":["Pin stable Vitest versions to avoid teardown/postMessage races.","Retry transient occurrences during cancellation.","Never call ThreadsPoolWorker.send after stop() when using the experimental API."],"tags":["worker","threads","internal-bug","lifecycle","assertion"],"analyzedSha":"d568f8ce3739b532d5bf2c1ee1e45e8a8a473d09","analyzedAt":"2026-08-03T20:23:56.861Z","schemaVersion":2}