vitest-dev/vitest · error · Error
Mock wasn't resolved. This is probably a Vitest error…
Error message
Mock ${id} wasn't resolved. This is probably a Vitest error. Please, open a new issue with reproduction. What it means
Thrown by `getFactoryModule(id)` after the mock is confirmed present and manual-typed, but `mock.cache` is falsy. `ManualMockedModule.cache` is populated only after `resolve()` (which executes the factory) completes successfully. A falsy cache means the factory was never resolved, or an async factory's promise has not settled yet. The message labels this a probable Vitest internal bug because `getFactoryModule` should only be called on already-resolved modules.
Solutions
- Ensure the factory returns synchronously (or that `resolveFactoryModule` is awaited) before any code reads the module.
- Check the factory for thrown errors — a throwing factory leaves `cache` undefined.
- Report a Vitest bug if the factory is synchronous and top-level but the error still appears.
Example fix
// before — async factory read before settlement
vi.mock('./mod', async () => ({ fn: await load() }))
// after — synchronous factory, or await resolution
vi.mock('./mod', () => ({ fn: vi.fn() })) Defensive patterns
Strategy: validation
Validate before calling
// Ensure the factory has resolved (cache populated) before reading it.
const mock = mocker.getMockedModuleById(id)
if (mock && mock.type === 'manual' && !(mock as any).cache) {
await mocker.resolveFactoryModule(id) // populate cache first
}
const cached = mocker.getFactoryModule(id) Type guard
function isResolvedManualMock(mock: unknown): mock is { type: 'manual'; cache: Record<string | symbol, any> } {
return typeof mock === 'object' && mock !== null
&& (mock as any).type === 'manual'
&& Boolean((mock as any).cache)
} Prevention
- Prefer synchronous factories in vi.mock so cache is populated immediately after resolve().
- Await resolveFactoryModule before any synchronous getFactoryModule read.
- Inspect factories for thrown errors that would leave cache undefined.
When it happens
Trigger: `getFactoryModule` is called before `resolveFactoryModule` (or `mock.resolve()`) has completed — e.g., a synchronous code path reads the cache while an async factory is still pending, or `resolve()` threw and cleared `cache` before `getFactoryModule` reads it.
Common situations: Browser mode with an async `vi.mock` factory that has not settled when the module is first imported; a factory that throws synchronously, leaving `cache` undefined; test-runner ordering bugs where the cache read races the resolution.
Related errors
- Mock wasn't registered. 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…
- Async schema validation is not supported in asymmetric…
AI-assisted analysis of vitest-dev/vitest@1fa9837ec2 (2026-08-11).
Data as JSON: /api/errors/49b82d5a3225ab55.
Report an issue: GitHub.
Appendix: source
Thrown at packages/mocker/src/browser/mocker.ts:46
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)
if (!ids.length) {
return
}
await this.rpc.invalidate(ids)
await this.interceptor.invalidate()
this.registry.clear()
}
public async importActual<T>(id: string, importer: string): Promise<T> {
const resolved = await this.rpc.resolveId(id, importer)
if (resolved == null) {
throw new Error(View on GitHub (pinned to 1fa9837ec2)