vitest-dev/vitest · error · Error
Cannot set serialized manual mock. Define a factory…
Error message
Cannot set serialized manual mock. Define a factory function manually with `ManualMockedModule.fromJSON()`.
What it means
Thrown by `MockerRegistry.register` (object-form) when `event.type === 'manual'`. Manual mocks carry a factory function, which cannot be serialized to JSON, so there is no way to reconstruct a `ManualMockedModule` from a plain object alone. The caller must instead use the multi-argument overload that supplies the factory function directly.
Solutions
- Use the multi-argument overload `register('manual', raw, id, url, factory)` to supply the factory function.
- If deserializing, call `ManualMockedModule.fromJSON(data, factory)` and then `registry.add(module)`.
- Ensure the transport layer reattaches the factory before registration rather than sending a bare JSON payload.
Example fix
// before — object path cannot carry a factory
registry.register({ type: 'manual', raw, id, url })
// after — multi-arg overload with factory
registry.register('manual', raw, id, url, () => ({ fn: vi.fn() })) Defensive patterns
Strategy: validation
Validate before calling
// Never send a manual mock through the object path; route it to the multi-arg overload.
function registerMock(registry: MockerRegistry, event: any) {
if (event.type === 'manual') {
throw new Error('Manual mocks must use the multi-arg register overload with a factory.')
}
return registry.register(event)
} Type guard
function isManualSerializedEvent(event: unknown): boolean {
return typeof event === 'object' && event !== null && (event as any).type === 'manual'
} Prevention
- Always pass manual mocks through the multi-arg register overload with a factory.
- If deserializing from JSON, reattach the factory via ManualMockedModule.fromJSON and use add().
- Keep the transport layer from round-tripping manual mocks as bare JSON.
When it happens
Trigger: A serialized manual-mock event arrives at `register` via the object path — e.g., an RPC message or IPC payload with `{ type: 'manual', ... }` and no accompanying factory. This happens when browser↔node mock coordination tries to round-trip a manual mock through JSON without reattaching the factory.
Common situations: Forking the mocker transport; a Vitest internal regression that routes manual mocks through the serialization path; custom interceptors that forward events verbatim.
Related errors
- Unknown mock type
- [vitest] Cannot register a mock that is already defined…
- [vitest] Mocks require a raw string.
- [vitest] Mocks require a url string.
- [vitest] Mocks require an id string.
AI-assisted analysis of vitest-dev/vitest@1fa9837ec2 (2026-08-11).
Data as JSON: /api/errors/3a97f298e5989c05.
Report an issue: GitHub.
Appendix: 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 1fa9837ec2)