vitest-dev/vitest · error · Error
Cannot set serialized manual mock. Define a factory function
Error message
Cannot set serialized manual mock. Define a factory function manually with `ManualMockedModule.fromJSON()`.
What it means
Manual mocks carry a JS factory closure that cannot be represented in JSON, so the registry refuses to rehydrate a serialized `{ type: 'manual' }` payload. To restore one you must supply the factory yourself via `ManualMockedModule.fromJSON(data, factory)` (or the positional register overload).
Source
Thrown at packages/mocker/src/registry.ts:87
)
}
if (event.type === 'automock') {
const module = AutomockedModule.fromJSON(event)
this.add(module)
return module
}
else if (event.type === 'autospy') {
const module = AutospiedModule.fromJSON(event)
this.add(module)
return module
}
else if (event.type === 'redirect') {
const module = RedirectedModule.fromJSON(event)
this.add(module)
return module
}
else if (event.type === 'manual') {
throw new Error(`Cannot set serialized manual mock. Define a factory function manually with \`ManualMockedModule.fromJSON()\`.`)
}
else {
throw new Error(`Unknown mock type: ${(event as any).type}`)
}
}
if (typeof raw !== 'string') {
throw new TypeError('[vitest] Mocks require a raw string.')
}
if (typeof url !== 'string') {
throw new TypeError('[vitest] Mocks require a url string.')
}
if (typeof id !== 'string') {
throw new TypeError('[vitest] Mocks require an id string.')
}
View on GitHub (pinned to d568f8ce37)
Solutions
- Reconstruct with an explicit factory: `const m = ManualMockedModule.fromJSON(data, () => ({ default: stub })); registry.add(m)`.
- Or register via the positional overload: `registry.register('manual', data.raw, data.id, data.url, factory)`.
- Do not attempt to round-trip manual mocks through JSON; transfer only their identity and rebuild the factory on the receiver.
Example fix
// before (fails — no factory)
registry.register({ type: 'manual', raw, id, url })
// after
registry.register('manual', data.raw, data.id, data.url, () => ({
default: vi.fn(),
})) Defensive patterns
Strategy: validation
Validate before calling
function registerManual(registry: any, data: any, factory: () => unknown) {
if (data?.type === 'manual' && typeof factory !== 'function') {
throw new Error('Manual mocks require a factory; cannot restore from JSON alone.')
}
if (data?.type === 'manual') {
registry.add(
ManualMockedModule.fromJSON(data, factory),
)
} else {
registry.register(data)
}
} Prevention
- Never attempt to serialize manual mocks for IPC without keeping the factory available on the receiver.
- Transfer only automock/autospy/redirect mocks as JSON; rebuild manual mocks locally.
- Document factory ownership in mock-sync code so receivers know to supply one.
When it happens
Trigger: Calling `registry.register({ type: 'manual', raw, id, url })` — the serialized form of a manual mock — without providing a factory function.
Common situations: Worker-thread mock sync where the main thread registered manual mocks; replaying serialized mock state; serializing a mock graph to disk and loading it back.
Related errors
- [vitest] Cannot register a mock that is already defined. Exp
- Unknown mock type: ${(event as any).type}
- [vitest] Manual mocks require a factory function.
- Mock ${id} wasn't registered. This is probably a Vitest erro
- Mock ${id} wasn't resolved. This is probably a Vitest error.
AI-assisted analysis of vitest-dev/vitest@d568f8ce37 (2026-08-03).
Data as JSON: /data/errors/3a97f298e5989c05.json.
Report an issue: GitHub.