mastra-ai/mastra · error · Error

Invalid browser configuration: "cdpUrl" cannot be used with

Error message

Invalid browser configuration: "cdpUrl" cannot be used with ${conflicting}.

• cdpUrl connects to an existing browser (which has its own profile and executable)
• profile and executablePath are launch-time options for spawning a new browser

To fix this, either:
1. Remove cdpUrl to launch a new browser with your profile/executable
2. Remove profile/executablePath to connect to the existing browser via CDP

What it means

cdpUrl connects to an already-running browser that carries its own profile and executable, so the launch-time options profile and executablePath make no sense alongside it. The constructor detects this conflict and throws with the list of conflicting options.

Source

Thrown at packages/core/src/browser/browser.ts:648

    const scope = config.scope;
    if (config.cdpUrl && scope === 'thread') {
      throw new Error(
        'Invalid browser configuration: "cdpUrl" and "scope: \'thread\'" cannot be used together.\n\n' +
          '• cdpUrl connects to a single existing browser instance (all threads share it)\n' +
          '• scope: "thread" requires spawning separate browser instances per thread\n\n' +
          'To fix this, either:\n' +
          '1. Remove cdpUrl to let the provider spawn separate browser instances (supports thread isolation)\n' +
          '2. Use scope: "shared" when connecting via cdpUrl (all threads share one browser)',
      );
    }

    // Validate: cdpUrl is incompatible with launch-time options (profile, executablePath).
    // CDP connects to an already-running browser — it has its own profile and executable.
    if (config.cdpUrl && (config.profile || config.executablePath)) {
      const conflicting = [config.profile && 'profile', config.executablePath && 'executablePath']
        .filter(Boolean)
        .join(' and ');
      throw new Error(
        `Invalid browser configuration: "cdpUrl" cannot be used with ${conflicting}.\n\n` +
          '• cdpUrl connects to an existing browser (which has its own profile and executable)\n' +
          '• profile and executablePath are launch-time options for spawning a new browser\n\n' +
          'To fix this, either:\n' +
          '1. Remove cdpUrl to launch a new browser with your profile/executable\n' +
          '2. Remove profile/executablePath to connect to the existing browser via CDP',
      );
    }
  }

  // ---------------------------------------------------------------------------
  // Lifecycle Management
  // ---------------------------------------------------------------------------

  /**
   * Launch the browser. Override in subclass.
   * Called by launch() wrapper which handles status and race conditions.
   */

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Remove profile/executablePath from the config to connect to the existing browser via CDP.
  2. Remove cdpUrl to launch a new browser with your profile/executable.
  3. When merging configs, delete launch-time keys whenever cdpUrl is present.

Example fix

// before
const browser = new Browser({
  cdpUrl: 'http://127.0.0.1:9222',
  executablePath: '/usr/bin/chromium', // conflict
  profile: '/tmp/profile',             // conflict
});
// after
const browser = new Browser({ cdpUrl: 'http://127.0.0.1:9222' });
Defensive patterns

Strategy: validation

Validate before calling

function sanitizeBrowserConfig(config) {
  if (config.cdpUrl) {
    const { profile, executablePath, ...rest } = config; // strip launch-time options
    return rest;
  }
  return config;
}
// call site:
const browser = new Browser(sanitizeBrowserConfig(rawConfig));

Type guard

function isCdpCompatibleConfig(config) {
  return !config.cdpUrl || (!config.profile && !config.executablePath);
}

Try / catch

try {
  browser = new Browser(config);
} catch (e) {
  if (e.message.includes('"cdpUrl" cannot be used with')) {
    const { profile, executablePath, ...rest } = config;
    browser = new Browser(rest); // prefer CDP connection
  } else throw e;
}

Prevention

When it happens

Trigger: Creating a Browser with cdpUrl set together with profile and/or executablePath in the same config object — e.g. merging a base launch config with a CDP override.

Common situations: Env-driven config where CDP_URL is provided but profile/executablePath defaults remain set; combining a local-Chrome config (executablePath) with a remote debugging URL; config spread/merge accidentally keeping stale launch options.

Related errors


AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30). Data as JSON: /api/errors/0560c72e7d534a1c. Report an issue: GitHub.