vitest-dev/vitest · error · Error

Unexpected message

Error message

Unexpected message ${JSON.stringify(message, null, 2)}

What it means

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.

Solutions

  1. Ensure the main process and workers run the same Vitest version/build (rebuild, reinstall).
  2. Check that no other process writes to the typecheck worker IPC channel.
  3. Read the printed JSON to identify which message type is unexpected, then map it to a version mismatch.
  4. If on a custom branch, verify message types are in sync between sender and worker.
Defensive patterns

Strategy: try-catch

Type guard

const isKnownMessage = (m: unknown): m is { type: 'run' | 'stop' } =>
  typeof m === 'object' && m !== null && typeof (m as any).type === 'string' && ['run', 'stop'].includes((m as any).type)

Try / catch

try {
  await workerHandler(message)
} catch (err) {
  if (err instanceof Error && err.message.startsWith('Unexpected message')) {
  console.error('Typecheck worker got an unknown message; check Vitest version sync:', err.message)
  return
  }
  throw err
}

Prevention

When it happens

Trigger: 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).

Common situations: 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.

Related errors


AI-assisted analysis of vitest-dev/vitest@1fa9837ec2 (2026-08-11). Data as JSON: /api/errors/eee85fec44bbe9f2. Report an issue: GitHub.

Appendix: source

Thrown at packages/vitest/src/node/pools/workers/typecheckWorker.ts:100

      return { type: 'testfileFinished', error, __vitest_worker_response__ }
    }

    case 'collect': {
      runPromise = runner.collectTests(message.context.files, project)
        .catch(error => error)
      const error = await runPromise

      return { type: 'testfileFinished', error, __vitest_worker_response__ }
    }

    case 'stop': {
      await runPromise
      return { type: 'stopped', __vitest_worker_response__ }
    }
  }

  throw new Error(`Unexpected message ${JSON.stringify(message, null, 2)}`)
}

function createRunner(vitest: Vitest) {
  const promisesMap = new WeakMap<TestProject, DeferPromise<void>>()
  const rerunTriggered = new WeakSet<TestProject>()

  async function onParseEnd(
    project: TestProject,
    { files, sourceErrors }: TypecheckResults,
  ) {
    const checker = project.typechecker!

    const { packs, events } = checker.getTestPacksAndEvents()
    await vitest._testRun.updated(packs, events)

    if (!project.config.typecheck.ignoreSourceErrors) {
      sourceErrors.forEach(error =>
        vitest.state.catchError(error, 'Unhandled Source Error'),

View on GitHub (pinned to 1fa9837ec2)