Skip to content

fix: validate browser process before reporting launch success#1379

Draft
eureka928 wants to merge 3 commits intoeigent-ai:mainfrom
eureka928:fix/browser-login-false-positive
Draft

fix: validate browser process before reporting launch success#1379
eureka928 wants to merge 3 commits intoeigent-ai:mainfrom
eureka928:fix/browser-login-false-positive

Conversation

@eureka928
Copy link
Contributor

@eureka928 eureka928 commented Feb 26, 2026

Summary

Fixes #1377POST /browser/login returned "success": true even when the Electron process exited immediately (e.g., sandbox misconfiguration, npx not found). The frontend (Cookies.tsx) also polled GET /browser/status which didn't exist, causing silent 404s.

Changes

Backend (tool_controller.py)

  • Add _login_browser_process module-level variable to track the subprocess
  • Add _wait_for_cdp_ready() helper that polls both process liveness and CDP port availability
  • Rewrite open_browser_login() to validate process state instead of blind asyncio.sleep(3)
  • Catch FileNotFoundError when npx is missing on PATH
  • Use run_in_executor for blocking readline() to avoid stalling the event loop
  • Add GET /browser/status endpoint the frontend already expects

Frontend (Cookies.tsx)

  • Check response?.success instead of just response (object is truthy even when success: false)
  • Show toast.error with the backend error message on failure

Before / After Proof

BEFORE (old behavior on main)

The old code blindly awaited asyncio.sleep(3) then returned success unconditionally:

# old code (main branch)
await asyncio.sleep(3)
return {
    "success": True,   # <-- always true, even if process crashed
    "pid": process.pid,
    ...
}

GET /browser/status did not exist → frontend polls got silent 404 errors.

AFTER (this PR)

Tested locally with uv run uvicorn main:api --port 5001:

=== TEST 1: GET /browser/status (no browser launched yet) ===
{"is_open":false}                                              ✅ New endpoint works

=== TEST 2: POST /browser/login (Electron crashes) ===
{"success":false,"error":"Browser process exited before CDP    ✅ Correctly reports failure
 became ready. Exit code: 1"}

=== TEST 3: GET /browser/status (after failed launch) ===
{"is_open":false}                                              ✅ Clean state after crash

=== TEST 4: POST /browser/login (retry) ===
{"success":false,"error":"Browser process exited before CDP    ✅ Consistent on retry
 became ready. Exit code: 1"}

Backend logs showing the process crash is detected and reported:

13:44:52 - tool_controller - INFO - [PROFILE USER LOGIN] Launching Electron browser with CDP on port 9223
13:44:52 - tool_controller - INFO - [ELECTRON OUTPUT] npm warn Unknown project config "shamefully-hoist"...
13:44:52 - tool_controller - INFO - [ELECTRON OUTPUT] [721291:...] FATAL:setuid_sandbox_host.cc(163)
  The SUID sandbox helper binary was found, but is not configured correctly...
13:44:53 - tool_controller - INFO - [ELECTRON OUTPUT] electron exited with signal SIGTRAP
13:44:53 - tool_controller - ERROR - [PROFILE USER LOGIN] Electron process exited with code: 1

Test plan

  • cd backend && uv run pytest — 402 passed, 11 skipped
  • TypeScript type-check — no new errors (pre-existing ones in skillsStore.ts only)
  • Manual: POST /browser/login returns success: false when Electron is unavailable
  • Manual: GET /browser/status returns {"is_open": false} when no browser is running
  • Manual: Retry after failure returns consistent results
  • Manual: With working Electron, success: true only after CDP port opens or process is confirmed alive

@eureka928
Copy link
Contributor Author

@Wendong-Fan would you review this PR?
Thank you

@eureka928 eureka928 force-pushed the fix/browser-login-false-positive branch from 15cc909 to 2d460a1 Compare February 26, 2026 12:56
@eureka928
Copy link
Contributor Author

@fengju0213 would you review this please?
Thank you for your time

@nitpicker55555
Copy link
Collaborator

@eureka928 can you provide video for the problem and the video after your solution?

Replace blind asyncio.sleep(3) with CDP port readiness check in
/browser/login. Catch FileNotFoundError when npx is missing, distinguish
process crash from CDP timeout, and add GET /browser/status endpoint
that the frontend already polls.
The fetchPost response is truthy even when success is false, so
if (response) always passed. Check response?.success instead and
show toast.error with the backend error message on failure.
Use run_in_executor for blocking readline so the event loop stays
responsive during the CDP readiness check. Treat the timeout case
(process alive, CDP slow) as success since the browser window is
already open for the user. Only report failure when the process
actually crashes.
@eureka928 eureka928 force-pushed the fix/browser-login-false-positive branch from b835323 to faf8de8 Compare March 3, 2026 12:39
@eureka928 eureka928 marked this pull request as draft March 3, 2026 13:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] /browser/login reports “launched” even if Electron exits quickly

2 participants