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
- 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.
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
- 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.
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
- The child process was torn down or never initialized. This…
- The worker thread was torn down or never initialized. This…
- Failed to load . Default export is missing.
- Test worker should expose "runTests" method. Received
- The browser configuration must have a "name" property. This…
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)