apify/crawlee · error · Error

Cannot extend LaunchContext with key: ${key}, because it's r

Error message

Cannot extend LaunchContext with key: ${key}, because it's reserved.

What it means

LaunchContext.extend() lets users attach arbitrary fields to a launch context, but some field names are internally reserved. If you pass a field whose name collides with a reserved internal field (e.g. launchOptions, useIncognitoPages, proxyUrl), extend() refuses to override it so internal behavior cannot be broken. The offending key name is included in the message.

Source

Thrown at packages/browser-pool/src/launch-context.ts:136

        this.#proxyUrl = proxyUrl;

        // Computed here (not in a field initializer) so that all fields already exist; the accessors live on
        // the prototype, so they are never own keys and have to be listed explicitly.
        this.#reservedFieldNames = [...Reflect.ownKeys(this), 'proxyUrl', 'remoteToken', 'extend'];
    }

    /**
     * Extend the launch context with any extra fields.
     * This is useful to keep state information relevant
     * to the browser being launched. It ensures that
     * no internal fields are overridden and should be
     * used instead of property assignment.
     */
    extend<T extends Record<PropertyKey, unknown>>(fields: T): void {
        Object.entries(fields).forEach(([key, value]) => {
            if (this.#reservedFieldNames.includes(key)) {
                throw new Error(`Cannot extend LaunchContext with key: ${key}, because it's reserved.`);
            } else {
                Reflect.set(this, key, value);
            }
        });
    }

    /**
     * Sets a proxy URL for the browser.
     * Use `undefined` to unset existing proxy URL.
     */
    set proxyUrl(url: string | undefined) {
        if (!url) {
            this.#proxyUrl = undefined;
            return;
        }

        const urlInstance = new URL(url);
        urlInstance.pathname = '/';

View on GitHub (pinned to dbe57fb09c)

Solutions

  1. Remove the reserved key from the object you pass to extend() and set it through the intended API (LaunchContext/PuppeteerPlugin/PlaywrightPlugin constructor options or launchOptions) instead.
  2. Filter the object before extending, e.g. omit keys like launchOptions, userDataDir, proxyUrl, useIncognitoPages.
  3. Check the reserved field list in packages/browser-pool/src/launch-context.ts to know which names are off-limits.

Example fix

// before
launchContext.extend({ proxyUrl: 'http://proxy:8080', myData: 1 });
// after
const { proxyUrl, ...custom } = options; // proxyUrl is reserved
launchContext.extend(custom);
// configure proxy via the plugin/launch context options instead
Defensive patterns

Strategy: validation

Validate before calling

const RESERVED = ['launchOptions', 'userDataDir', 'proxyUrl', 'useIncognitoPages', 'experimentalContainers'];
const safe = Object.fromEntries(Object.entries(fields).filter(([k]) => !RESERVED.includes(k)));
launchContext.extend(safe);

Type guard

function hasReservedKeys(obj: Record<string, unknown>, reserved: string[]): boolean {
  return Object.keys(obj).some((k) => reserved.includes(k));
}

Try / catch

try {
  launchContext.extend(fields);
} catch (err) {
  if (err instanceof Error && err.message.startsWith('Cannot extend LaunchContext')) {
    console.warn(`Dropping reserved key: ${err.message.match(/key: ([^,]+)/)?.[1]}`);
  } else throw err;
}

Prevention

When it happens

Trigger: Calling launchContext.extend({ key: value }) where key is one of LaunchContext's #reservedFieldNames (its own internal configuration properties, such as launchOptions, userDataDir, proxyUrl, useIncognitoPages, experimentalContainers).

Common situations: Passing a whole options object (e.g. spreading launch options or plugin config) into extend() without filtering out reserved keys; renaming/refactors that introduce a key that collides with an internal field; attempting to override proxy or headless settings via extend instead of the proper constructor/launch options.

Related errors


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