{"record":{"id":"eee85fec44bbe9f2","repo":"vitest-dev/vitest","slug":"unexpected-message-json-stringify-message-null","errorCode":null,"errorMessage":"Unexpected message ${JSON.stringify(message, null, 2)}","messagePattern":"Unexpected message (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/vitest/src/node/pools/workers/typecheckWorker.ts","lineNumber":100,"sourceCode":"\n      return { type: 'testfileFinished', error, __vitest_worker_response__ }\n    }\n\n    case 'collect': {\n      runPromise = runner.collectTests(message.context.files, project)\n        .catch(error => error)\n      const error = await runPromise\n\n      return { type: 'testfileFinished', error, __vitest_worker_response__ }\n    }\n\n    case 'stop': {\n      await runPromise\n      return { type: 'stopped', __vitest_worker_response__ }\n    }\n  }\n\n  throw new Error(`Unexpected message ${JSON.stringify(message, null, 2)}`)\n}\n\nfunction createRunner(vitest: Vitest) {\n  const promisesMap = new WeakMap<TestProject, DeferPromise<void>>()\n  const rerunTriggered = new WeakSet<TestProject>()\n\n  async function onParseEnd(\n    project: TestProject,\n    { files, sourceErrors }: TypecheckResults,\n  ) {\n    const checker = project.typechecker!\n\n    const { packs, events } = checker.getTestPacksAndEvents()\n    await vitest._testRun.updated(packs, events)\n\n    if (!project.config.typecheck.ignoreSourceErrors) {\n      sourceErrors.forEach(error =>\n        vitest.state.catchError(error, 'Unhandled Source Error'),","sourceCodeStart":82,"sourceCodeEnd":118,"githubUrl":"https://github.com/vitest-dev/vitest/blob/1fa9837ec26533512fdcad8baebf249771bd340a/packages/vitest/src/node/pools/workers/typecheckWorker.ts#L82-L118","documentation":"The typecheck worker's message handler is a switch over the incoming message type. After handling 'run'/'stop'-style cases, reaching the end means the message shape was unrecognized. The handler throws with the full JSON of the message so the unexpected payload is visible in the error.","triggerScenarios":"The typecheck worker process receives a message whose 'type' field does not match any known case (e.g. a message from a mismatched Vitest version, a corrupted IPC frame, or a new message type the worker build does not know).","commonSituations":"Mixed Vitest versions between the main process and the typecheck worker, a partially built Vitest where the worker has older message definitions, or third-party tooling posting into the worker channel.","solutions":["Ensure the main process and workers run the same Vitest version/build (rebuild, reinstall).","Check that no other process writes to the typecheck worker IPC channel.","Read the printed JSON to identify which message type is unexpected, then map it to a version mismatch.","If on a custom branch, verify message types are in sync between sender and worker."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":"const isKnownMessage = (m: unknown): m is { type: 'run' | 'stop' } =>\n  typeof m === 'object' && m !== null && typeof (m as any).type === 'string' && ['run', 'stop'].includes((m as any).type)","tryCatchPattern":"try {\n  await workerHandler(message)\n} catch (err) {\n  if (err instanceof Error && err.message.startsWith('Unexpected message')) {\n  console.error('Typecheck worker got an unknown message; check Vitest version sync:', err.message)\n  return\n  }\n  throw err\n}","preventionTips":["Keep main process and typecheck worker on the same Vitest version/build.","Do not inject messages into the typecheck worker IPC channel.","Rebuild Vitest after source changes."],"tags":["internal-bug","typecheck","worker-pool","ipc","version-mismatch"],"backgroundTag":null,"analyzedSha":"1fa9837ec26533512fdcad8baebf249771bd340a","analyzedAt":"2026-08-11T16:11:39.638Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}