{"id":"aa5c8dbf1cf053ac","repo":"vitest-dev/vitest","slug":"vitest-cannot-register-a-mock-that-is-already-de","errorCode":null,"errorMessage":"[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.","messagePattern":"\\[vitest\\] Cannot register a mock that is already defined\\. Expected a JSON representation from `MockedModule\\.toJSON`, instead got \"(.+?)\"\\. Use \"registry\\.add\\(\\)\" to update a mock instead\\.","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"packages/mocker/src/registry.ts","lineNumber":65,"sourceCode":"  ): AutospiedModule\n  public register(\n    typeOrEvent: MockedModuleType | MockedModuleSerialized,\n    raw?: string,\n    id?: string,\n    url?: string,\n    factoryOrRedirect?: string | (() => any),\n  ): MockedModule {\n    const type = typeof typeOrEvent === 'object' ? typeOrEvent.type : typeOrEvent\n\n    if (typeof typeOrEvent === 'object') {\n      const event = typeOrEvent\n      if (\n        event instanceof AutomockedModule\n        || event instanceof AutospiedModule\n        || event instanceof ManualMockedModule\n        || event instanceof RedirectedModule\n      ) {\n        throw new TypeError(\n          `[vitest] Cannot register a mock that is already defined. `\n          + `Expected a JSON representation from \\`MockedModule.toJSON\\`, instead got \"${event.type}\". `\n          + `Use \"registry.add()\" to update a mock instead.`,\n        )\n      }\n      if (event.type === 'automock') {\n        const module = AutomockedModule.fromJSON(event)\n        this.add(module)\n        return module\n      }\n      else if (event.type === 'autospy') {\n        const module = AutospiedModule.fromJSON(event)\n        this.add(module)\n        return module\n      }\n      else if (event.type === 'redirect') {\n        const module = RedirectedModule.fromJSON(event)\n        this.add(module)","sourceCodeStart":47,"sourceCodeEnd":83,"githubUrl":"https://github.com/vitest-dev/vitest/blob/d568f8ce3739b532d5bf2c1ee1e45e8a8a473d09/packages/mocker/src/registry.ts#L47-L83","documentation":"`MockerRegistry.register()` is overloaded to accept either positional args (build a new mock) or a plain serialized JSON object (rehydrate a mock transferred between processes). Passing an already-constructed `MockedModule` class instance is rejected because the registry expects the DTO shape produced by `toJSON()`. Use `registry.add()` to insert a live instance directly.","triggerScenarios":"Calling `registry.register(existingModule)` where `existingModule` is an instance of `AutomockedModule`/`AutospiedModule`/`ManualMockedModule`/`RedirectedModule` rather than `existingModule.toJSON()`.","commonSituations":"Worker-thread mock synchronization forwarding live instances; internal tooling that wraps mocks; replaying a captured mock registry without serializing.","solutions":["Serialize the instance first: `registry.register(mock.toJSON())`.","Or add the instance directly: `registry.add(mock)` (no validation/clone, just insert).","If forwarding between processes, always call `.toJSON()` before IPC and reconstruct on the other side."],"exampleFix":"// before\nregistry.register(existingMock)\n\n// after\nregistry.register(existingMock.toJSON())\n// or, for a live instance on the same process:\nregistry.add(existingMock)","handlingStrategy":"type-guard","validationCode":"import {\n  AutomockedModule, AutospiedModule,\n  ManualMockedModule, RedirectedModule,\n} from '@vitest/mocker/registry'\n\nfunction isMockInstance(v: unknown) {\n  return v instanceof AutomockedModule\n    || v instanceof AutospiedModule\n    || v instanceof ManualMockedModule\n    || v instanceof RedirectedModule\n}\n\n// route live instances to add(), DTOs to register()\nfunction upsert(registry: any, mock: unknown) {\n  if (isMockInstance(mock)) registry.add(mock)\n  else registry.register(mock)\n}","typeGuard":"function isSerializedMockDTO(v: unknown): v is { type: string } {\n  return typeof v === 'object' && v !== null\n    && typeof (v as any).type === 'string'\n    && !(v instanceof AutomockedModule\n      || v instanceof AutospiedModule\n      || v instanceof ManualMockedModule\n      || v instanceof RedirectedModule)\n}","tryCatchPattern":null,"preventionTips":["Always call `.toJSON()` before forwarding a mock across a process boundary.","Use `registry.add()` for live instances and `registry.register()` for DTOs — never mix.","Centralize mock registration in a helper that branches on instance vs DTO."],"tags":["mocking","registry","serialization","ipc"],"analyzedSha":"d568f8ce3739b532d5bf2c1ee1e45e8a8a473d09","analyzedAt":"2026-08-03T20:23:56.861Z","schemaVersion":2}