vitest-dev/vitest · error · TypeError
[vitest] Cannot register a mock that is already defined…
Error message
[vitest] Cannot register a mock that is already defined. Expected a JSON representation from `MockedModule.toJSON`, instead got "${event.type}". Use "registry.add()" to update a mock instead. What it means
Thrown as a `TypeError` by `MockerRegistry.register` when the object-form argument is an instance of one of the concrete mock classes (`AutomockedModule`, `AutospiedModule`, `ManualMockedModule`, `RedirectedModule`) rather than a plain JSON-serializable object. `register` expects the output of `MockedModule.toJSON()`; to store an already-constructed instance the caller must use `registry.add()` instead.
Solutions
- Use `registry.add(mockInstance)` when you already have a constructed `MockedModule`.
- Pass `mockInstance.toJSON()` to `register` if you need the JSON-deserialization path.
- Switch to the multi-argument overload (`register(type, raw, id, url, ...)`) when constructing from primitives.
Example fix
// before — passing an instance to register const mock = new ManualMockedModule(raw, id, url, factory) registry.register(mock) // after — use add for instances registry.add(mock)
Defensive patterns
Strategy: type-guard
Validate before calling
// Distinguish instances from JSON payloads before calling register vs add.
import { AutomockedModule, AutospiedModule, ManualMockedModule, RedirectedModule } from '@vitest/mocker'
function isMockedModuleInstance(value: unknown): boolean {
return value instanceof AutomockedModule
|| value instanceof AutospiedModule
|| value instanceof ManualMockedModule
|| value instanceof RedirectedModule
}
if (isMockedModuleInstance(payload)) {
registry.add(payload)
} else {
registry.register(payload as any)
} Type guard
import type { MockedModule } from '@vitest/mocker'
function isMockedModule(value: unknown): value is MockedModule {
return value instanceof AutomockedModule
|| value instanceof AutospiedModule
|| value instanceof ManualMockedModule
|| value instanceof RedirectedModule
} Prevention
- Use registry.add() for constructed instances; reserve register() for JSON payloads.
- Add an internal wrapper that routes instances to add() and JSON to register().
When it happens
Trigger: Calling `registry.register(mockInstance)` with a constructed `MockedModule` instance instead of calling `registry.add(mockInstance)` or passing `mockInstance.toJSON()`. This is an internal API misuse — end users do not call `register` directly.
Common situations: Forking Vitest or writing a custom mocker that constructs module instances and passes them to `register` instead of `add`; refactoring that confuses the object-JSON overload with the instance-overload.
Related errors
- [vitest] Mocks require a raw string.
- [vitest] Mocks require a url string.
- [vitest] Mocks require an id string.
- Cannot set serialized manual mock. Define a factory…
- Unknown mock type
AI-assisted analysis of vitest-dev/vitest@1fa9837ec2 (2026-08-11).
Data as JSON: /api/errors/aa5c8dbf1cf053ac.
Report an issue: GitHub.
Appendix: source
Thrown at packages/mocker/src/registry.ts:65
): AutospiedModule
public register(
typeOrEvent: MockedModuleType | MockedModuleSerialized,
raw?: string,
id?: string,
url?: string,
factoryOrRedirect?: string | (() => any),
): MockedModule {
const type = typeof typeOrEvent === 'object' ? typeOrEvent.type : typeOrEvent
if (typeof typeOrEvent === 'object') {
const event = typeOrEvent
if (
event instanceof AutomockedModule
|| event instanceof AutospiedModule
|| event instanceof ManualMockedModule
|| event instanceof RedirectedModule
) {
throw new TypeError(
`[vitest] Cannot register a mock that is already defined. `
+ `Expected a JSON representation from \`MockedModule.toJSON\`, instead got "${event.type}". `
+ `Use "registry.add()" to update a mock instead.`,
)
}
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)View on GitHub (pinned to 1fa9837ec2)