← Back to PRs

#4663: fix: per-profile browser caching to allow parallel connections

by tsukhani open 2026-01-30 13:46 View on GitHub →
## Summary Changes global singleton `cached`/`connecting` variables to per-URL Maps, allowing different browser profiles to connect in parallel instead of blocking each other. ## Problem When using multiple browser profiles (e.g., `linkedin` on port 18805 and `clawd` on port 18800), operations on one profile blocked operations on the other due to shared global state. ## Solution - Replace `let cached` and `let connecting` with `Map<string, ...>` keyed by CDP URL - Each profile now maintains its own connection state - `closePlaywrightBrowserConnection()` now closes all cached connections ## Testing - [x] Tested locally with multiple browser profiles - [x] Linter passes ## AI Assistance 🤖 This PR was AI-assisted (Claude). The fix was identified by analyzing the root cause reported in #4289 and #3605. Fixes #4289, #3605 <!-- greptile_comment --> <h2>Greptile Overview</h2> <h3>Greptile Summary</h3> This PR changes Playwright CDP connection caching from a single global `cached`/`connecting` pair to per-CDP-URL Maps (`cachedByUrl`, `connectingByUrl`), allowing multiple browser profiles (different CDP URLs) to connect concurrently without blocking each other. It also updates `closePlaywrightBrowserConnection()` to close all cached browser connections rather than just the last cached one. The approach fits the existing `connectBrowser()` pattern (normalize URL → connect with retry → observe browser) while removing cross-profile contention introduced by global singleton state. <h3>Confidence Score: 4/5</h3> - This PR is likely safe to merge and addresses the reported cross-profile connection contention. - The change is localized to connection caching logic and appears consistent with existing connection/retry patterns. Main remaining concern is lifecycle: clearing `connectingByUrl` in `closePlaywrightBrowserConnection()` can leave in-flight connections untracked and potentially open, which could matter if callers rely on close being deterministic during concurrent usage. - src/browser/pw-session.ts (connection lifecycle during concurrent close/connect) <!-- greptile_other_comments_section --> <!-- /greptile_comment -->

Most Similar PRs