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

  1. Ensure setConfiguration() is called only once, before any service is retrieved from the locator.
  2. Pass the same Configuration instance consistently; do not build a new Configuration for a second call.
  3. Create a fresh ServiceLocator (or reset it) if you truly need to swap configurations.
  4. 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

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


AI-assisted analysis of apify/crawlee@dbe57fb09c (2026-08-30). Data as JSON: /api/errors/5f3eb19cf24a77f3. Report an issue: GitHub.