{"record":{"id":"0a3d728f65878649","repo":"mastra-ai/mastra","slug":"invalid-browser-configuration-cdpurl-and-scope","errorCode":null,"errorMessage":"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\nTo fix this, either:\n1. Remove cdpUrl to let the provider spawn separate browser instances (supports thread isolation)\n2. Use scope: \"shared\" when connecting via cdpUrl (all threads share one browser)","messagePattern":"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\nTo fix this, either:\n1\\. Remove cdpUrl to let the provider spawn separate browser instances \\(supports thread isolation\\)\n2\\. Use scope: \"shared\" when connecting via cdpUrl \\(all threads share one browser\\)","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/core/src/browser/browser.ts","lineNumber":632,"sourceCode":"  private _closePromise?: Promise<void>;\n\n  // ---------------------------------------------------------------------------\n  // Constructor\n  // ---------------------------------------------------------------------------\n\n  constructor(config: BrowserConfig = {}) {\n    super({ name: 'MastraBrowser', component: RegisteredLogger.BROWSER });\n    this.config = config;\n\n    // Validate configuration: cdpUrl and scope: 'thread' are mutually exclusive\n    // When connecting to an external browser via cdpUrl, we connect to a single existing browser.\n    // Thread isolation requires spawning separate browser instances, which isn't possible with cdpUrl.\n    // Note: The BrowserConfig type enforces this at compile-time, but we keep this runtime check\n    // for better error messages when users bypass TypeScript (e.g., from JavaScript or casting).\n    // We capture scope before checking cdpUrl to avoid TypeScript narrowing the union type.\n    const scope = config.scope;\n    if (config.cdpUrl && scope === 'thread') {\n      throw new Error(\n        'Invalid browser configuration: \"cdpUrl\" and \"scope: \\'thread\\'\" cannot be used together.\\n\\n' +\n          '• cdpUrl connects to a single existing browser instance (all threads share it)\\n' +\n          '• scope: \"thread\" requires spawning separate browser instances per thread\\n\\n' +\n          'To fix this, either:\\n' +\n          '1. Remove cdpUrl to let the provider spawn separate browser instances (supports thread isolation)\\n' +\n          '2. Use scope: \"shared\" when connecting via cdpUrl (all threads share one browser)',\n      );\n    }\n\n    // Validate: cdpUrl is incompatible with launch-time options (profile, executablePath).\n    // CDP connects to an already-running browser — it has its own profile and executable.\n    if (config.cdpUrl && (config.profile || config.executablePath)) {\n      const conflicting = [config.profile && 'profile', config.executablePath && 'executablePath']\n        .filter(Boolean)\n        .join(' and ');\n      throw new Error(\n        `Invalid browser configuration: \"cdpUrl\" cannot be used with ${conflicting}.\\n\\n` +\n          '• cdpUrl connects to an existing browser (which has its own profile and executable)\\n' +","sourceCodeStart":614,"sourceCodeEnd":650,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/core/src/browser/browser.ts#L614-L650","documentation":"The Browser constructor rejects configurations that combine cdpUrl (connect to one existing browser via Chrome DevTools Protocol) with scope: 'thread' (which requires spawning a separate browser per thread). TypeScript types prevent this at compile time, but a runtime check gives a clear message when the config is built dynamically in JS or via casts.","triggerScenarios":"Creating a Browser with a config object containing both cdpUrl and scope: 'thread', typically assembled dynamically (from env vars, a DB record, or JS without type checking).","commonSituations":"Config sourced from environment/feature flags where cdpUrl is set for production while scope stays 'thread' from the default; JS callers bypassing the BrowserConfig discriminated-union types; copy-pasting cdpUrl examples into a thread-scoped setup.","solutions":["Remove cdpUrl so the provider spawns separate browser instances per thread (keeps thread isolation).","Change scope to 'shared' when connecting via cdpUrl, accepting that all threads share one browser.","Make the config source mutually exclusive: only read cdpUrl when scope is 'shared' (or undefined)."],"exampleFix":"// before\nconst browser = new Browser({ cdpUrl: process.env.CDP_URL, scope: 'thread' }); // throws\n// after\nconst browser = process.env.CDP_URL\n  ? new Browser({ cdpUrl: process.env.CDP_URL, scope: 'shared' })\n  : new Browser({ scope: 'thread' });","handlingStrategy":"validation","validationCode":"function buildBrowserConfig(opts) {\n  if (opts.cdpUrl && opts.scope === 'thread') {\n    throw new Error('cdpUrl cannot be combined with scope \"thread\"; use scope \"shared\" or drop cdpUrl');\n  }\n  return opts;\n}\n// call site:\nconst browser = new Browser(buildBrowserConfig(rawOptions));","typeGuard":"function isValidBrowserConfig(config) {\n  if (config.cdpUrl && config.scope === 'thread') return false;\n  return true;\n}","tryCatchPattern":"let browser;\ntry {\n  browser = new Browser(config);\n} catch (e) {\n  if (e.message.includes('cdpUrl') && e.message.includes(\"scope: 'thread'\")) {\n    browser = new Browser({ ...config, scope: 'shared' });\n  } else throw e;\n}","preventionTips":["Centralize browser config construction in one typed helper so TS unions block bad combos.","Never spread raw env/DB values into BrowserConfig without normalizing scope first.","When cdpUrl is present, force scope to 'shared' by default."],"tags":["browser","configuration","cdp","validation"],"backgroundTag":"invalid-browser-config","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}