vitest-dev/vitest · error · Error
Mock wasn't registered. This is probably a Vitest error…
Error message
Mock ${id} wasn't registered. This is probably a Vitest error. Please, open a new issue with reproduction. What it means
Thrown by `ModuleMocker.resolveFactoryModule(id)` (browser mode) when the registry lookup for `id` returns either nothing or a mock whose `type` is not `'manual'`. This method is called to execute a `vi.mock(path, factory)` factory at import time; reaching it with an unregistered or wrong-typed mock means the hoisting/registration pipeline did not populate the registry as expected. The message explicitly flags it as a likely Vitest internal bug.
Solutions
- Ensure `vi.mock(path, factory)` calls are at the top level of the test file so they are hoisted and registered before any import.
- Avoid calling `vi.unmock` and then importing the same module in the same test without re-registering the mock.
- If using a custom test runner, verify it awaits `mocker.prepare()` before importing test modules.
- Report a Vitest bug with a browser-mode reproduction if the error persists with top-level `vi.mock`.
Example fix
// before — vi.mock nested inside a test body
it('works', () => {
vi.mock('./mod', () => ({ fn: () => 1 }))
require('./mod')
})
// after — hoisted to top level
vi.mock('./mod', () => ({ fn: () => 1 }))
it('works', () => {
require('./mod')
}) Defensive patterns
Strategy: validation
Validate before calling
// Before calling resolveFactoryModule, confirm the mock is registered as manual.
const mock = mocker.getMockedModuleById(id)
if (!mock || mock.type !== 'manual') {
throw new Error(`Cannot resolve factory for ${id}: not registered as a manual mock`)
}
await mocker.resolveFactoryModule(id) Type guard
import type { ManualMockedModule } from '@vitest/mocker'
function isManualMock(mock: unknown): mock is ManualMockedModule {
return typeof mock === 'object' && mock !== null && (mock as any).type === 'manual'
} Prevention
- Always place vi.mock(path, factory) at module top level so registration completes before imports.
- Await mocker.prepare() before importing modules that depend on mocks.
- Avoid calling vi.unmock for a module whose factory is still pending resolution.
When it happens
Trigger: The browser-side mocker's `resolveFactoryModule` is invoked for a module id that was never registered via `queueMock` → `registry.register('manual', ...)`, or whose registration resolved to an `automock`/`autospy`/`redirect` type instead. Typical when `prepare()` (which drains the registration queue) has not completed before the dynamic import triggers resolution, or when `invalidate()` cleared the registry mid-test.
Common situations: Browser mode tests where `vi.mock` is called conditionally or after the module is already imported; race conditions between `vi.unmock` and a pending import; HMR or test isolation logic that calls `registry.clear()` before all factories resolve.
Related errors
- Mock wasn't resolved. This is probably a Vitest error…
- automocking files with `export *` is not supported because…
- Unknown mock type
- AssignmentPattern is not supported. Please open a new bug…
- Cannot find iframe with id
AI-assisted analysis of vitest-dev/vitest@1fa9837ec2 (2026-08-11).
Data as JSON: /api/errors/ab2ee311224bae86.
Report an issue: GitHub.
Appendix: source
Thrown at packages/mocker/src/browser/mocker.ts:34
constructor(
private interceptor: ModuleMockerInterceptor,
private rpc: ModuleMockerRPC,
private createMockInstance: CreateMockInstanceProcedure,
private config: ModuleMockerConfig,
) {}
public async prepare(): Promise<void> {
if (!this.queue.size) {
return
}
await Promise.all([...this.queue.values()])
}
public async resolveFactoryModule(id: string): Promise<Record<string | symbol, any>> {
const mock = this.registry.get(id)
if (!mock || mock.type !== 'manual') {
throw new Error(`Mock ${id} wasn't registered. This is probably a Vitest error. Please, open a new issue with reproduction.`)
}
const result = await mock.resolve()
return result
}
public getFactoryModule(id: string): any {
const mock = this.registry.get(id)
if (!mock || mock.type !== 'manual') {
throw new Error(`Mock ${id} wasn't registered. This is probably a Vitest error. Please, open a new issue with reproduction.`)
}
if (!mock.cache) {
throw new Error(`Mock ${id} wasn't resolved. This is probably a Vitest error. Please, open a new issue with reproduction.`)
}
return mock.cache
}
public async invalidate(): Promise<void> {
const ids = Array.from(this.mockedIds)View on GitHub (pinned to 1fa9837ec2)