jackwener/OpenCLI · error · BrowserConnectError
profile-required
profile-required
Error message
Multiple Browser Bridge profiles are connected
What it means
ensureBrowserBridgeReady found the daemon health in state 'profile-required', meaning multiple Browser Bridge profiles/contexts are connected and the caller must specify which one to use. The library throws BrowserConnectError with code profile-required because it cannot disambiguate the target context.
Source
Thrown at src/browser/daemon-lifecycle.ts:143
}
if (!portReleased) {
throw new BrowserConnectError(
'Stale daemon could not be replaced',
`A stale daemon (${reason}) is running but did not shut down (graceful + SIGKILL both failed).\n` +
' Run manually: opencli daemon stop',
'daemon-not-running',
);
}
staleDaemonReplaced = true;
}
if (!staleDaemonReplaced && health.state === 'ready') {
return health;
}
if (!staleDaemonReplaced && health.state === 'profile-required') {
throw browserConnectErrorFromHealth(health, contextId);
}
if (staleDaemonReplaced || health.state === 'stopped') {
if (verbose && (process.env.OPENCLI_VERBOSE || process.stderr.isTTY)) {
process.stderr.write('⏳ Starting daemon...\n');
}
daemonLifecycleHooks.spawnDaemonProcess();
} else if (verbose && (process.env.OPENCLI_VERBOSE || process.stderr.isTTY)) {
process.stderr.write('⏳ Waiting for Chrome/Chromium extension to connect...\n');
process.stderr.write(' Make sure Chrome or Chromium is open and the OpenCLI extension is enabled.\n');
}
const finalHealth = await waitForBridgeReady(getDaemonHealth, { timeoutMs, contextId, preferredContextId });
if (finalHealth.state === 'ready') return finalHealth;
throw browserConnectErrorFromHealth(finalHealth, contextId);
}
function browserConnectErrorFromHealth(health: DaemonHealth, contextId?: string): BrowserConnectError {View on GitHub (pinned to 49907e53dc)
Solutions
- Pass an explicit context/profile ID to the command so the bridge knows which connected profile to target.
- Close or disconnect the extra Chrome profiles/windows running the OpenCLI extension.
- Restart the daemon so only one profile reconnects, then rerun the command.
- Check daemon health output to list connected profiles and pick the correct contextId.
Example fix
// before
await runCommand('browser', 'click', { selector: '#go' });
// after: disambiguate the profile
await runCommand('browser', 'click', { selector: '#go', contextId: 'work-profile' }); Defensive patterns
Strategy: validation
Validate before calling
const health = await bridge.health();
if (health.state === 'profile-required') {
// supply a contextId before running commands
} Type guard
function isProfileRequired(health) {
return health.state === 'profile-required';
} Try / catch
try {
await runCommand('browser', action, args);
} catch (e) {
if (e.code === 'profile-required') {
return runCommand('browser', action, { ...args, contextId: pickProfileId() });
}
throw e;
} Prevention
- Always pass an explicit contextId when multiple Chrome profiles run the extension.
- Run only one browser profile with the OpenCLI extension enabled.
- Check daemon health before batch runs to detect multi-profile states early.
- Disconnect stale daemon sessions from previous runs.
When it happens
Trigger: Calling any Browser Bridge-backed command (via _ensureDaemon or health) when the daemon reports more than one connected profile and no contextId/preferredContextId was supplied; the code path browserConnectErrorFromHealth(health, contextId) converts the health state into this error.
Common situations: Multiple Chrome profiles (personal + work) running the OpenCLI extension, several browser windows across profiles connected simultaneously, or leftover daemon connections from a previous session.
Related errors
- OPENCLI_DAEMON_PORT is no longer supported${suffix}. The Ope
- daemon-not-running
- Detached HEAD — checkout a branch first
- Missing ${label}
- Invalid ${label}: ${raw}
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/c0ec6d1febb34126.
Report an issue: GitHub.