{"record":{"id":"0ab15c7debc6113a","repo":"apify/crawlee","slug":"serviceconflicterror-eventmanager-eventmanager","errorCode":null,"errorMessage":"ServiceConflictError('EventManager', eventManager, this.#eventManager)","messagePattern":"ServiceConflictError\\('EventManager', eventManager, this\\.#eventManager\\)","errorType":"exception","errorClass":"ServiceConflictError","httpStatus":null,"severity":"error","filePath":"packages/core/src/service_locator.ts","lineNumber":229,"sourceCode":"                this.getLogger().warning(\n                    'Implicit creation of event manager will implicitly set configuration as side effect. ' +\n                        'It is advised to explicitly first set the configuration instead.',\n                );\n            }\n            this.#eventManager = LocalEventManager.fromConfiguration(this.getConfiguration());\n        }\n        return this.#eventManager;\n    }\n\n    setEventManager(eventManager: EventManager): void {\n        // Same instance, no need to do anything\n        if (this.#eventManager === eventManager) {\n            return;\n        }\n\n        // Already have a different event manager that was retrieved\n        if (this.#eventManager) {\n            throw new ServiceConflictError('EventManager', eventManager, this.#eventManager);\n        }\n\n        this.#eventManager = eventManager;\n    }\n\n    getStorageBackend(): StorageBackend {\n        if (!this.#storageBackend) {\n            this.getLogger().debug(\n                'No storage backend set, implicitly creating and using the default storage backend ' +\n                    '(FileSystemStorageBackend when persistStorage is enabled, MemoryStorageBackend otherwise).',\n            );\n            if (!this.#configuration) {\n                this.getLogger().warning(\n                    'Implicit creation of storage backend will implicitly set configuration as side effect. ' +\n                        'It is advised to explicitly first set the configuration instead.',\n                );\n            }\n            const configuration = this.getConfiguration();","sourceCodeStart":211,"sourceCodeEnd":247,"githubUrl":"https://github.com/apify/crawlee/blob/dbe57fb09ca607ad59dcf998f3925ef9ac3bb26c/packages/core/src/service_locator.ts#L211-L247","documentation":"setEventManager() throws ServiceConflictError if a different EventManager instance is registered when one already exists in the ServiceLocator. This guards the singleton invariant: all components must share one EventManager so events route consistently.","triggerScenarios":"Calling setEventManager(emA), then setEventManager(emB) with a different EventManager instance; or retrieving the event manager first and later trying to inject a custom one.","commonSituations":"Manually wiring a custom EventManager after crawlee already initialized one (e.g. by creating a crawler or accessing events), or double initialization in tests/HMR.","solutions":["Register your custom EventManager before anything else initializes the default one.","Reuse the existing event manager (getEventManager()) instead of constructing a new one.","Only call setEventManager() once per locator lifetime.","Reset/recreate the ServiceLocator between test cases that each set their own event manager."],"exampleFix":"// before\nconst crawler = new CheerioCrawler(...); // initializes default EventManager\nlocator.setEventManager(myEventManager); // throws\n\n// after\nconst locator = new ServiceLocator();\nlocator.setEventManager(myEventManager); // before any retrieval\nconst crawler = new CheerioCrawler({ ..., serviceLocator: locator });","handlingStrategy":"validation","validationCode":"let existing;\ntry { existing = locator.getEventManager(); } catch { existing = null; }\nif (existing && existing !== myEventManager) { /* skip registration */ }","typeGuard":null,"tryCatchPattern":"try {\n    locator.setEventManager(em);\n} catch (e) {\n    if (e instanceof ServiceConflictError) em = locator.getEventManager();\n    else throw e;\n}","preventionTips":["Inject custom EventManager only during initial wiring, before any crawler/storage access.","Subscribe to the existing manager's events instead of replacing it.","Keep locator setup in a single shared bootstrap module."],"tags":["event-manager","dependency-injection","lifecycle"],"backgroundTag":"service-already-configured","analyzedSha":"dbe57fb09ca607ad59dcf998f3925ef9ac3bb26c","analyzedAt":"2026-08-30T22:22:28.328Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}