openclaw/openclaw · error · BrowserProfileUnavailableError
Chrome MCP existing-session attach failed for profile "${pro
Error message
Chrome MCP existing-session attach failed for profile "${profileName}". The Chrome MCP subprocess exited before it became usable. What it means
Thrown as BrowserProfileUnavailableError (HTTP 409) by leaseSession when, after waitForChromeMcpReady reported the session ready, the transport PID was null on a second consecutive attempt (staleReadySessionRetries > 1). It means the Chrome MCP subprocess became ready and then immediately exited, twice in a row, so attaching is considered impossible for this profile right now.
Source
Thrown at extensions/browser/src/browser/chrome-mcp-session.ts:166
leasedPending = createdPending;
pendingLease = await waitForSharedPendingChromeMcpSession(createdPending, signal);
session = pendingLease.session;
}
try {
await waitForChromeMcpReady(session, profileName, timeoutMs, signal);
if (session.transport.pid === null) {
forgetCachedChromeMcpSessionIfCurrent(cacheKey, session);
if (leasedPending) {
forgetPendingChromeMcpSessionIfCurrent(cacheKey, leasedPending);
}
if (pendingLease) {
await pendingLease.release(true);
pendingLease = undefined;
}
staleReadySessionRetries += 1;
if (staleReadySessionRetries > 1) {
throw new BrowserProfileUnavailableError(
`Chrome MCP existing-session attach failed for profile "${redactChromeMcpProfileLabelForDiagnostic(profileName)}". ` +
"The Chrome MCP subprocess exited before it became usable.",
);
}
continue;
}
return session;
} catch (err) {
if (signal?.aborted && pendingLease) {
await pendingLease.release(true);
pendingLease = undefined;
} else if (pendingLease && leasedPending && leasedPending.state.waiters > 1) {
await pendingLease.release(false);
pendingLease = undefined;
} else {
forgetCachedChromeMcpSessionIfCurrent(cacheKey, session);
if (leasedPending) {
forgetPendingChromeMcpSessionIfCurrent(cacheKey, leasedPending);View on GitHub (pinned to 01804a7531)
Solutions
- Run the Chrome MCP binary manually with the same flags and inspect stderr for the crash cause (missing lib, sandbox denial, lock error).
- Ensure no other Chrome instance is using the same user-data-dir; remove a stale SingletonLock if a previous Chrome crashed.
- On locked-down containers, configure the sandbox appropriately (or the documented container setup) rather than retrying blindly.
- Check that Chrome/Chromium is installed at a supported version and that the profile's executablePath points to it.
Example fix
# before: profile launches a crashing Chrome # (configured executablePath points at incompatible chrome) # after: reproduce the crash manually to see the real error CHROME_LOG=$(mktemp) "$CHROME_BIN" --remote-debugging-port=9222 \ --user-data-dir="$PROFILE_DIR" about:blank 2>"$CHROME_LOG" cat "$CHROME_LOG" # inspect missing lib / sandbox / lock error
Defensive patterns
Strategy: retry
Validate before calling
// Pre-flight: confirm Chrome binary runs and the user-data-dir is not locked
import { execFileSync } from "node:child_process";
try {
execFileSync(chromePath, ["--version"], { stdio: "pipe", timeout: 2_000 });
} catch {
// Chrome missing/unrunnable; fix before attempting to attach
}
if (existsSync(path.join(profileDir, "SingletonLock"))) {
// stale lock from a crashed Chrome; remove only if no Chrome is running
} Type guard
import { BrowserProfileUnavailableError } from "./errors.js";
function isAttachFailedError(err: unknown): err is BrowserProfileUnavailableError {
return err instanceof BrowserProfileUnavailableError && /exited before it became usable/.test(err.message);
} Try / catch
try {
return await leaseSession(profileName, opts, timeoutMs, signal);
} catch (err) {
if (err instanceof BrowserProfileUnavailableError && /exited before it became usable/.test(err.message)) {
// reproduce the Chrome crash manually (see exampleFix) before retrying
throw new Error("Chrome MCP crashes on startup; run the binary manually to inspect.");
}
throw err;
} Prevention
- Run the Chrome MCP binary manually with the same flags to see the crash cause.
- Ensure the user-data-dir is not locked by another Chrome instance.
- Install required shared libraries and a supported Chrome/Chromium version.
- Configure the sandbox appropriately for the runtime (container vs host).
When it happens
Trigger: Chrome MCP subprocess starts, signals ready, then crashes before its PID can be relied upon; on retry the same thing happens. Causes include bad launch flags, missing shared libraries, sandbox/seccomp killing the process, an incompatible Chrome/Chromium version, or a user-data-dir lock held by another Chrome instance.
Common situations: Chrome not installed or wrong version; user-data-dir already locked by a running Chrome with the same profile; missing libs in a minimal container; sandbox requiring --no-sandbox in the environment but not configured; incompatible Chrome MCP binary for the host architecture.
Related errors
- Chrome MCP session for profile "${profileName}" changed befo
- Unable to inspect the Chrome MCP process tree.
- Chrome MCP process identity unavailable for pid ${rootPid}.
- Chrome MCP subprocess tree cleanup could not be verified.
- Chrome MCP process cleanup failed for pid ${surviving.map(({
AI-assisted analysis of openclaw/openclaw@01804a7531 (2026-08-12).
Data as JSON: /api/errors/7afb0ff4997f5ea7.
Report an issue: GitHub.