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

  1. Use `registry.add(mockInstance)` when you already have a constructed `MockedModule`.
  2. Pass `mockInstance.toJSON()` to `register` if you need the JSON-deserialization path.
  3. 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

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


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)