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
- Remove profile/executablePath from the config to connect to the existing browser via CDP.
- Remove cdpUrl to launch a new browser with your profile/executable.
- 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
- Treat cdpUrl as an exclusive mode: when merging configs, delete profile/executablePath whenever cdpUrl is set.
- Keep launch-time options and CDP options in separate config branches, never one flat object.
- Add a unit test asserting sanitized configs for both CDP and launch modes.
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
- Invalid browser configuration: "cdpUrl" and "scope: 'thread'
- Google RBAC roleMapping is required.
- Cookie password must be at least 32 characters. Set OKTA_COO
- browser_close requires agent.threadId when browser scope is
- No browser context available for screencast
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/0560c72e7d534a1c.
Report an issue: GitHub.