apify/crawlee · error · Error

${crawlerName}: ${names.map((name) => `\`${name}\``).join(',

Error message

${crawlerName}: ${names.map((name) => `\`${name}\``).join(', ')} cannot be combined with `browserPool`, ${names.length > 1 ? 'they configure' : 'it configures'} the browser pool the crawler would build for itself. Configure the pool you pass in instead.

What it means

Browser-based crawlers (CheerioCrawler aside) can accept an externally constructed browserPool. Options that configure the internally built pool (e.g. launchContext, browserPoolOptions, proxyConfiguration) are mutually exclusive with a user-supplied browserPool. assertBrowserPoolNotConfigured throws when both are provided.

Source

Thrown at packages/browser-crawler/src/internals/browser-crawler.ts:73

 * The type of a browser pool the crawler builds (and therefore owns) for itself. It's an {@apilink IBrowserPool} that
 * additionally exposes `destroy()` — the crawler only ever tears down pools it created, which is why {@apilink IBrowserPool}
 * itself intentionally omits `destroy`.
 */
export type OwnedBrowserPool<Page> = IBrowserPool<Page> & { destroy: () => Promise<void> };

/**
 * Rejects options that exist only to configure the browser pool the crawler would have built for itself.
 * Accepting them alongside a pre-built `browserPool` and quietly ignoring them is how `browserPoolOptions` grew
 * into a second, half-working way of configuring the same pool.
 */
export function assertBrowserPoolNotConfigured(crawlerName: string, ignoredOptions: Dictionary): void {
    const names = Object.keys(ignoredOptions).filter((name) => ignoredOptions[name] !== undefined);

    if (names.length === 0) {
        return;
    }

    throw new Error(
        `${crawlerName}: ${names.map((name) => `\`${name}\``).join(', ')} cannot be combined with \`browserPool\`, ` +
            `${names.length > 1 ? 'they configure' : 'it configures'} the browser pool the crawler would build for ` +
            'itself. Configure the pool you pass in instead.',
    );
}

type ContextDifference<T, U> = Omit<U, keyof T> & Partial<U>;

export interface BrowserCrawlingContext<
    Page extends CommonPage = CommonPage,
    Response extends BaseResponse = BaseResponse,
    UserData extends Dictionary = any, // with default to Dictionary we cant use a typed router in untyped crawler
    GoToOptions extends Dictionary = Dictionary,
> extends CrawlingContext<UserData> {
    /**
     * The browser page object where the web page is loaded and rendered.
     */
    page: Page;

View on GitHub (pinned to dbe57fb09c)

Solutions

  1. Remove the conflicting options (launchContext, browserPoolOptions, proxyConfiguration, etc.) and configure the browserPool instance directly instead
  2. Or drop the browserPool argument and let the crawler build its own pool from those options
  3. Configure the passed-in pool before handing it to the crawler (hooks, plugins, proxies on the pool itself)

Example fix

// before
const crawler = new PuppeteerCrawler({ browserPool: myPool, launchContext: { launchOptions: { headless: true } } });
// after
myPool.hooks.onBrowserLaunched?.(...); // configure myPool itself
const crawler = new PuppeteerCrawler({ browserPool: myPool });
Defensive patterns

Strategy: validation

Validate before calling

const poolOptions = ['launchContext','browserPoolOptions','proxyConfiguration'].filter(k => k in options && options[k] !== undefined);
if ('browserPool' in options && poolOptions.length) throw new Error(`Options ${poolOptions} conflict with browserPool`);

Prevention

When it happens

Trigger: Constructing e.g. new PuppeteerCrawler({ browserPool, launchContext: {...} }) or { browserPool, browserPoolOptions } / { browserPool, proxyConfiguration } - any pool-configuring option set alongside browserPool.

Common situations: Migrating from default construction to dependency-injected pools while leaving old launch/proxy options in place; copy-pasting crawler configs and adding browserPool.

Related errors


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