apify/crawlee · error · ServiceConflictError

ServiceConflictError('Logger', logger, this.#logger)

Error message

ServiceConflictError('Logger', logger, this.#logger)

What it means

setLogger() throws ServiceConflictError if a different CrawleeLogger is registered after one already exists in the ServiceLocator. The library assumes a single logger instance so all components emit logs through the same sink.

Solutions

  1. Inject the custom logger before any crawlee component initializes (before crawler construction or storage access).
  2. Reuse getLogger() and wrap/extend it rather than replacing it.
  3. Call setLogger() only once per ServiceLocator lifetime.
  4. Prefer configuring log level via Log.getLogLevel()/log options rather than swapping logger instances.

Example fix

// before
const crawler = new PlaywrightCrawler(...); // default logger registered
locator.setLogger(myLogger); // throws

// after
const locator = new ServiceLocator();
locator.setLogger(myLogger);
const crawler = new PlaywrightCrawler({ ..., serviceLocator: locator });
Defensive patterns

Strategy: validation

Validate before calling

let existing;
try { existing = locator.getLogger(); } catch { existing = null; }
if (existing && existing !== myLogger) { /* logger already registered */ }

Try / catch

try {
    locator.setLogger(logger);
} catch (e) {
    if (e instanceof ServiceConflictError) {
        const base = locator.getLogger();
        logger = Object.assign(Object.create(Object.getPrototypeOf(base)), logger);
    } else throw e;
}

Prevention

When it happens

Trigger: Calling setLogger(loggerA) then setLogger(loggerB); or using the default logger implicitly and later trying to inject a custom logger via the locator.

Common situations: Installing a custom log implementation after crawlee initialization, or in tests where multiple setups each register a logger on the shared locator.

Related errors


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

Appendix: source

Thrown at packages/core/src/service_locator.ts:287

        }

        this.#storageBackend = storageBackend;
    }

    getLogger(): CrawleeLogger {
        if (!this.#logger) {
            this.#logger = new ApifyLogAdapter(log);
        }
        return this.#logger;
    }

    setLogger(logger: CrawleeLogger): void {
        if (this.#logger === logger) {
            return;
        }

        if (this.#logger) {
            throw new ServiceConflictError('Logger', logger, this.#logger);
        }

        this.#logger = logger;
    }

    getChildLog(prefix: string): CrawleeLogger {
        return this.getLogger().child({ prefix });
    }

    getStorageInstanceManager(): StorageInstanceManager {
        if (!ServiceLocator.#storageInstanceManager) {
            ServiceLocator.#storageInstanceManager = new StorageInstanceManager();
        }
        return ServiceLocator.#storageInstanceManager;
    }

    reset(): void {
        this.#configuration = undefined;

View on GitHub (pinned to dbe57fb09c)