{"record":{"id":"775c064de039400d","repo":"vercel-labs/agent-browser","slug":"cannot-use-cacert-with-clearcacert","errorCode":null,"errorMessage":"Cannot use caCert with clearCaCert","messagePattern":"Cannot use caCert with clearCaCert","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/@agent-browser/eve/extension/lib/browser.ts","lineNumber":145,"sourceCode":"  if ((probe.exitCode ?? 0) === 0) {\n    return;\n  }\n  await withDeadline(\n    installAgentBrowser(sandbox, {\n      abortSignal,\n      installBrowser: config.installBrowser,\n      installSpec: config.installSpec,\n      installSystemDependencies: config.installSystemDependencies,\n    }),\n    \"Installing agent-browser\",\n  );\n}\n\nfunction configArgs(): string[] {\n  const config = extension.config;\n  const args: string[] = [];\n  if (config.caCert !== undefined && config.clearCaCert) {\n    throw new Error(\"Cannot use caCert with clearCaCert\");\n  }\n  if (config.allowedDomains !== undefined && config.allowedDomains.length > 0) {\n    args.push(\"--allowed-domains\", config.allowedDomains.join(\",\"));\n  }\n  if (config.caCert !== undefined) {\n    args.push(\"--ca-cert\", config.caCert);\n  } else if (config.clearCaCert) {\n    args.push(\"--no-ca-cert\");\n  }\n  if (config.contentBoundaries) {\n    args.push(\"--content-boundaries\");\n  }\n  if (config.maxOutputChars !== undefined) {\n    args.push(\"--max-output\", String(config.maxOutputChars));\n  }\n  if (config.proxy !== undefined) {\n    args.push(\"--proxy\", config.proxy);\n  }","sourceCodeStart":127,"sourceCodeEnd":163,"githubUrl":"https://github.com/vercel-labs/agent-browser/blob/f9a6cc34212340dad62b114559f7a306c4be0707/packages/@agent-browser/eve/extension/lib/browser.ts#L127-L163","documentation":"This error is thrown by configArgs() in the eve extension's browser launcher (packages/@agent-browser/eve/extension/lib/browser.ts:144). configArgs() turns the extension config into agent-browser CLI flags: caCert maps to --ca-cert <path> (trust a custom certificate authority) and clearCaCert maps to --no-ca-cert (remove a previously configured CA). The two flags contradict each other, so the guard throws before any browser process is started.","triggerScenarios":"Any browser command issued while extension.config has both a defined caCert value and clearCaCert set to true, for example { caCert: '/etc/ssl/corp-ca.pem', clearCaCert: true }. configArgs() runs while building the command line, so the throw fires on the first tool call, before the sandbox or browser is touched. The guard checks caCert !== undefined, so an empty string still triggers it.","commonSituations":"Persisted or layered config where a stale caCert string survives a merge (defaults plus user settings plus environment) while clearCaCert: true is added later to remove the cert; switching a shared config template from set-cert to clear-cert without deleting the old key; generated CI config that carries both keys because one layer sets a cert and another clears it.","solutions":["Pick one intent: to trust a CA, keep caCert and delete clearCaCert; to remove the CA, keep clearCaCert: true and delete caCert (or set it to undefined).","If the config is merged from multiple sources, set caCert to undefined explicitly in the layer that adds clearCaCert: true; a leftover stale or empty string still counts as set.","To replace an existing certificate, pass the new caCert path alone; the stored cert is overwritten, so clearCaCert is not needed first.","Add a startup validation that rejects the combination with a clear message before the first browser command runs."],"exampleFix":"// before — throws: Cannot use caCert with clearCaCert\nconst config = { caCert: '/certs/corp-ca.pem', clearCaCert: true };\n\n// after — trust a (new) CA\nconst config = { caCert: '/certs/corp-ca.pem' };\n\n// after — remove the CA entirely\nconst config = { clearCaCert: true };","handlingStrategy":"validation","validationCode":"// Run before registering the extension or issuing any browser command\nfunction validateEveBrowserConfig(config) {\n  if (config.caCert !== undefined && config.clearCaCert) {\n    throw new Error('Invalid config: caCert and clearCaCert are mutually exclusive');\n  }\n}\nvalidateEveBrowserConfig(extension.config);","typeGuard":"// Cert settings are a tri-state: unset, set, or clear — never two at once\nfunction hasCoherentCertConfig(config) {\n  return !(config.caCert !== undefined && config.clearCaCert === true);\n}","tryCatchPattern":"try {\n  await runBrowserCommand();\n} catch (err) {\n  if (err instanceof Error && err.message === 'Cannot use caCert with clearCaCert') {\n    // Decide the intent, drop the other key, retry once\n    delete extension.config.clearCaCert; // or: extension.config.caCert = undefined;\n    await runBrowserCommand();\n  } else {\n    throw err;\n  }\n}","preventionTips":["Treat caCert and clearCaCert as one tri-state field: undefined means no change, a string sets the cert, clearCaCert removes it. Never populate two states at once.","When configs are merged or persisted, resolve the cert fields to a single final value before handing the config to the extension.","The guard checks caCert !== undefined, not truthiness; an empty string still triggers the error, so delete the key or set it to undefined.","Validate the config once at startup with a schema check or a small validator instead of discovering the conflict at the first browser launch."],"tags":["configuration","mutually-exclusive-flags","ca-cert","tls","validation"],"backgroundTag":"mutually-exclusive-options","analyzedSha":"f9a6cc34212340dad62b114559f7a306c4be0707","analyzedAt":"2026-08-23T02:32:15.041Z","contentChangedAt":"2026-08-23T02:32:15.041Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}