[Bug] Session health check rebuilds Chrome with a fresh profile when the driver's backend-tab connection is lost — discards login state
Repo: platonai/Browser4 · Module: browser4-rest (ai.platon.pulsar.rest.session.PulsarSessionManager)
Component: Session health check / auto-replacement
Severity: Medium — silent loss of interactive session state (manual logins, cookies, form state)
Version observed: browser4 runtime v4.13.5 (CLI backend), Windows 11, headed Chrome
Summary
When the driver link to a session's backend tab is lost while the browser process itself is still healthy, the session health check declares the session "unhealthy" and rebuilds the whole browser with a fresh profile (a new cx.NNN user-data dir). Any state that lived in the old profile — most importantly a manual GitHub (or any site) login — is silently discarded, and the user sees an anonymous, logged-out browser.
In our reproduction, the driver link died after the machine went through Modern Standby (Windows S0 sleep). After wake, eval/snapshot still worked for ~20 minutes, then the first click hung (CDP DOM.getContentQuads got no response for 30 s), and the health check immediately tore down the session.
Steps to reproduce
browser4-cli -s demo open --headed "https://github.com/<repo>" (any site with a login).
- Log in manually in the visible window (e.g., GitHub).
- Let the machine enter Modern Standby (sleep) for a while, then wake it. (Alternative trigger: manually close the hidden "backend tab" the driver bridges through, if visible in the tab strip.)
- Interact with the page through the CLI — e.g.
browser4-cli -s demo click <ref>.
- Observe: the click hangs ~30 s and fails; the backend then replaces the session with a brand-new Chrome profile, and the manual login is gone.
Observed behavior (log evidence, local times)
19:39:03 (Windows event log: Kernel-Power 507/566 — exiting Modern Standby)
...
19:52:29 Calling tool: browser_click --ref=backend:8631 --sessionId=...
19:52:34 RobustRPC: Oop, a bit slip-up executing action: [evaluateDetail], retrying 1/2 time ... | Timed out waiting for 5000 ms
19:53:04 ClickableDOM: Failed to get content quads for node 3682
ChromeRPCTimeoutException: No response | DOM.getContentQuads | #5, (PT30S)
19:53:04 PulsarSessionManager - Bound driver 4 is unhealthy, state: INIT
19:53:04 Session <id> is unhealthy: session active=true,
browser healthy=CheckState(code=0, message=Browser is healthy, scope=),
driver healthy=CheckState(code=503, message=WebDriver is not open - the connection to the backend tab is lost, scope=)
19:53:04 Cached session <id> is unhealthy, creating a replacement
19:53:05 ChromeLauncher - DevTools listening on ws://127.0.0.1:19096 (NEW Chrome, fresh profile cx.002)
Key observations:
- The browser itself was healthy (
code=0) — the visible window kept working fine the whole time; only the driver→backend-tab link was dead (code=503, driver stuck in INIT).
- The replacement used a new user-data dir (
cx.001 → cx.002), so profile-scoped state (cookies, logins) was lost.
- A plain CDP attach to the old Chrome (
ws://127.0.0.1:56233/...) still worked afterwards — the old browser and its profile were perfectly usable; only the backend's bookkeeping about them was broken.
- The health check fired on the next CLI interaction after the link died, so the failure is user-visible as a random "session reset".
Expected behavior
A dead driver link should not destroy the session's browser/profile. Prefer, in order:
- Reconnect / recreate the backend tab for the existing browser (the driver is in
INIT — let it finish re-initializing against the same Chrome), or
- Keep the old profile when rebuilding (reuse the same user-data dir), or
- At least fail the operation loudly instead of silently swapping to a fresh anonymous browser.
The health check should distinguish "browser process dead" (rebuild warranted) from "browser healthy but driver link lost" (recover the link). Note the log line even prints browser healthy=code=0 immediately before deciding to throw the browser away.
Suggested fix direction
In PulsarSessionManager (see is unhealthy/creating a replacement around lines 159–220 and 719–721 of browser4-rest/src/main/kotlin/ai/platon/pulsar/rest/session/PulsarSessionManager.kt):
- When
browser healthy == OK but driver healthy == 503 (backend-tab link lost), attempt a driver re-init against the existing Chrome (the driver is already in INIT state) with a bounded retry, instead of creating a replacement.
- Only fall back to profile-preserving rebuild if re-init fails.
- Consider a config/flag to disable auto-replacement for interactive (headed) sessions, since silent profile swaps are especially harmful there.
Workarounds
- After logging in manually, save the session state (
browser4-cli state-save) so it can be restored after a rebuild.
- Operate via direct CDP attach to the headed Chrome (
browser4-cli attach --cdp http://127.0.0.1:<port>, or raw page-level CDP) to bypass the session manager entirely.
- Avoid machine sleep while a headed interactive session is mid-work.
Repro notes
- Triggering link death: machine Modern Standby (Windows 11, S0) is a reliable repro; manually closing the backend tab should also work.
- Affects all headed interactive workflows that require manual login (GitHub, cloud consoles, etc.).
[Bug] Session health check rebuilds Chrome with a fresh profile when the driver's backend-tab connection is lost — discards login state
Repo: platonai/Browser4 · Module:
browser4-rest(ai.platon.pulsar.rest.session.PulsarSessionManager)Component: Session health check / auto-replacement
Severity: Medium — silent loss of interactive session state (manual logins, cookies, form state)
Version observed: browser4 runtime v4.13.5 (CLI backend), Windows 11, headed Chrome
Summary
When the driver link to a session's backend tab is lost while the browser process itself is still healthy, the session health check declares the session "unhealthy" and rebuilds the whole browser with a fresh profile (a new
cx.NNNuser-data dir). Any state that lived in the old profile — most importantly a manual GitHub (or any site) login — is silently discarded, and the user sees an anonymous, logged-out browser.In our reproduction, the driver link died after the machine went through Modern Standby (Windows S0 sleep). After wake,
eval/snapshotstill worked for ~20 minutes, then the firstclickhung (CDPDOM.getContentQuadsgot no response for 30 s), and the health check immediately tore down the session.Steps to reproduce
browser4-cli -s demo open --headed "https://github.com/<repo>"(any site with a login).browser4-cli -s demo click <ref>.Observed behavior (log evidence, local times)
Key observations:
code=0) — the visible window kept working fine the whole time; only the driver→backend-tab link was dead (code=503, driver stuck inINIT).cx.001→cx.002), so profile-scoped state (cookies, logins) was lost.ws://127.0.0.1:56233/...) still worked afterwards — the old browser and its profile were perfectly usable; only the backend's bookkeeping about them was broken.Expected behavior
A dead driver link should not destroy the session's browser/profile. Prefer, in order:
INIT— let it finish re-initializing against the same Chrome), orThe health check should distinguish "browser process dead" (rebuild warranted) from "browser healthy but driver link lost" (recover the link). Note the log line even prints
browser healthy=code=0immediately before deciding to throw the browser away.Suggested fix direction
In
PulsarSessionManager(seeis unhealthy/creating a replacementaround lines 159–220 and 719–721 ofbrowser4-rest/src/main/kotlin/ai/platon/pulsar/rest/session/PulsarSessionManager.kt):browser healthy == OKbutdriver healthy == 503(backend-tab link lost), attempt a driver re-init against the existing Chrome (the driver is already inINITstate) with a bounded retry, instead of creating a replacement.Workarounds
browser4-cli state-save) so it can be restored after a rebuild.browser4-cli attach --cdp http://127.0.0.1:<port>, or raw page-level CDP) to bypass the session manager entirely.Repro notes