vitest-dev/vitest · error · Error
Unknown mock type
Error message
Unknown mock type: ${(mock as any).type} What it means
Thrown by the MSW-based browser module interceptor when a registered mock's `type` does not match any of the handled cases (`manual`, `automock`, `autospy`, `redirect`) in the request-handler switch. The interceptor serves mocked modules over HTTP in browser mode; reaching the `default` branch means the registry holds a mock whose type is outside the `MockedModuleType` union. This is a defensive guard that should be unreachable under normal use.
Solutions
- If you forked Vitest or wrote a custom interceptor, extend the switch in `interceptor-msw.ts` to handle your custom mock type.
- Update Vitest to the latest patch release — this branch indicates an internal inconsistency that may already be fixed.
- File a Vitest bug report with a minimal browser-mode reproduction, since the four union types should make this unreachable in stock Vitest.
Defensive patterns
Strategy: type-guard
Validate before calling
// Before adding a mock to the MSW interceptor, confirm its type is one the handler switch covers.
const HANDLED_MOCK_TYPES = new Set(['manual', 'automock', 'autospy', 'redirect'])
function isHandledMockType(mock: { type: string }): boolean {
return HANDLED_MOCK_TYPES.has(mock.type)
}
if (!isHandledMockType(mock)) {
throw new Error(`Refusing to register mock with unsupported type: ${mock.type}`)
} Type guard
function isKnownMockType(mock: unknown): mock is { type: 'manual' | 'automock' | 'autospy' | 'redirect' } {
return typeof mock === 'object' && mock !== null
&& typeof (mock as any).type === 'string'
&& ['manual', 'automock', 'autospy', 'redirect'].includes((mock as any).type)
} Prevention
- Treat the four-type MockedModuleType union as exhaustive; any new type must update both the registry and every interceptor switch.
- In forked code, add a type-narrowing wrapper around registry.add so unsupported types fail at registration, not at request time.
- Keep browser-side and node-side mocker versions in sync to avoid type-set drift.
When it happens
Trigger: A mock object with an unexpected `type` string is stored in the `ModuleMockerMSWInterceptor.mocks` registry and then served by the `http.get(/.+/)` handler. This can happen if a custom/forked interceptor registers a non-standard mock class, or if the registry is corrupted by a race during concurrent `register()`/`invalidate()` calls.
Common situations: Running Vitest browser mode with a forked or patched mocker that introduces a new mock type without extending the switch; concurrent test file teardown that mutates the registry while a request is in flight; a Vitest internal regression after adding a new `MockedModuleType` without updating the interceptor.
Related errors
- Mock wasn't registered. This is probably a Vitest error…
- Mock wasn't resolved. This is probably a Vitest error…
- Unknown mock type
- automocking files with `export *` is not supported because…
- Cannot set serialized manual mock. Define a factory…
AI-assisted analysis of vitest-dev/vitest@1fa9837ec2 (2026-08-11).
Data as JSON: /api/errors/989009ec131275ae.
Report an issue: GitHub.
Appendix: source
Thrown at packages/mocker/src/browser/interceptor-msw.ts:109
const worker = setupWorker(
http.get(/.+/, async ({ request }) => {
const path = cleanQuery(request.url.slice(location.origin.length))
if (!this.mocks.has(path)) {
return passthrough()
}
const mock = this.mocks.get(path)!
switch (mock.type) {
case 'manual':
return this.resolveManualMock(mock)
case 'automock':
case 'autospy':
return Response.redirect(injectQuery(path, `mock=${mock.type}`))
case 'redirect':
return Response.redirect(mock.redirect)
default:
throw new Error(`Unknown mock type: ${(mock as any).type}`)
}
}),
)
return worker.start(this.options.mswOptions).then(() => worker)
}).finally(() => {
this.worker = worker
this.startPromise = undefined
})
return await this.startPromise
}
}
const trailingSeparatorRE = /[?&]$/
const timestampRE = /\bt=\d{13}&?\b/
const versionRE = /\bv=\w{8}&?\b/
function cleanQuery(url: string) {
return url.replace(timestampRE, '').replace(versionRE, '').replace(trailingSeparatorRE, '')
}View on GitHub (pinned to 1fa9837ec2)