apify/crawlee · error · ServiceConflictError
ServiceConflictError('Configuration', configuration, this.#c
Error message
ServiceConflictError('Configuration', configuration, this.#configuration) What it means
ServiceLocator allows each service to be registered at most once. setConfiguration() throws ServiceConflictError when a different Configuration instance is provided after one has already been set/retrieved. Identical instances are idempotent (no-op), so this only fires on genuine conflicts between two distinct Configuration objects.
Source
Thrown at packages/core/src/service_locator.ts:201
}
getConfiguration(): Configuration {
if (!this.#configuration) {
this.getLogger().debug('No configuration set, implicitly creating and using default Configuration.');
this.#configuration = new Configuration();
}
return this.#configuration;
}
setConfiguration(configuration: Configuration): void {
// Same instance, no need to do anything
if (this.#configuration === configuration) {
return;
}
// Already have a different configuration that was retrieved
if (this.#configuration) {
throw new ServiceConflictError('Configuration', configuration, this.#configuration);
}
this.#configuration = configuration;
}
getEventManager(): EventManager {
if (!this.#eventManager) {
this.getLogger().debug('No event manager set, implicitly creating and using default LocalEventManager.');
if (!this.#configuration) {
this.getLogger().warning(
'Implicit creation of event manager will implicitly set configuration as side effect. ' +
'It is advised to explicitly first set the configuration instead.',
);
}
this.#eventManager = LocalEventManager.fromConfiguration(this.getConfiguration());
}
return this.#eventManager;
}View on GitHub (pinned to dbe57fb09c)
Solutions
- Ensure setConfiguration() is called only once, before any service is retrieved from the locator.
- Pass the same Configuration instance consistently; do not build a new Configuration for a second call.
- Create a fresh ServiceLocator (or reset it) if you truly need to swap configurations.
- In tests, isolate the locator per test or clear module state between tests to avoid stale registrations.
Example fix
// before
Configuration.global.set('storageOptions', opts);
locator.setConfiguration(new Configuration()); // conflicts
// after
const config = Configuration.getGlobalConfig();
config.set('storageOptions', opts);
locator.setConfiguration(config); // same instance, no conflict Defensive patterns
Strategy: validation
Validate before calling
if (locator.getConfiguration && locator.getConfiguration() !== myConfig) {
// a different configuration already registered – do not call setConfiguration again
} Try / catch
try {
locator.setConfiguration(config);
} catch (e) {
if (e instanceof ServiceConflictError) {
console.warn('Configuration already set; reusing existing one.');
} else throw e;
} Prevention
- Call setConfiguration() exactly once at process startup.
- Reuse Configuration.getGlobalConfig() instead of constructing new instances.
- In tests, create a fresh ServiceLocator per test.
When it happens
Trigger: Calling locator.setConfiguration(cfgA) (or retrieving configuration via getConfiguration()) and then calling locator.setConfiguration(cfgB) with a different Configuration instance.
Common situations: Initializing crawlee twice in one process (e.g. in tests or HMR reloads), globalConfiguration vs. a manually built Configuration, or a module importing crawlee under two different paths so two Configuration instances exist.
Related errors
- Cannot set() a borrowed OwnedOrInjected value
- ServiceConflictError('EventManager', eventManager, this.#eve
- ServiceConflictError('StorageBackend', storageBackend, this.
- ServiceConflictError('Logger', logger, this.#logger)
- The `minConcurrency`/`maxConcurrency`/`initialConcurrency`/`
AI-assisted analysis of apify/crawlee@dbe57fb09c (2026-08-30).
Data as JSON: /api/errors/5f3eb19cf24a77f3.
Report an issue: GitHub.