#21277: fix(browser): dedupe concurrent relay init and await shared startup promise (AI-assisted)
size: XS
Cluster:
Chrome Extension Enhancements
## Summary
- Problem: Concurrent relay initialization on the same port could race and produce flaky startup/error behavior.
- Why it matters: Browser extension relay startup reliability suffers under concurrent calls.
- What changed: Added shared per-port init coordination and ensured callers await the same startup lifecycle; added/updated relay tests.
- What did NOT change (scope boundary): Did not alter relay auth model (gateway-token flow remains unchanged).
## Change Type (select all)
- [x] Bug fix
- [ ] Feature
- [ ] Refactor
- [ ] Docs
- [ ] Security hardening
- [ ] Chore/infra
## Scope (select all touched areas)
- [ ] Gateway / orchestration
- [ ] Skills / tool execution
- [ ] Auth / tokens
- [ ] Memory / storage
- [x] Integrations
- [ ] API / contracts
- [ ] UI / DX
- [ ] CI/CD / infra
## Linked Issue/PR
- Closes #
- Related #20688
## User-visible / Behavior Changes
- Browser extension relay startup is more deterministic under concurrent initialization.
- Reduced startup race flakiness when multiple callers initialize relay simultaneously.
## Security Impact (required)
- New permissions/capabilities? (`No`)
- Secrets/tokens handling changed? (`No`)
- New/changed network calls? (`No`)
- Command/tool execution surface changed? (`No`)
- Data access scope changed? (`No`)
- If any `Yes`, explain risk + mitigation: `N/A`
## Repro + Verification
### Environment
- OS: macOS (local dev)
- Runtime/container: Node.js + pnpm
- Model/provider: N/A (unit tests)
- Integration/channel (if any): Browser extension relay
- Relevant config (redacted): OPENCLAW_GATEWAY_TOKEN set in tests
### Steps
1. Start relay initialization concurrently for the same requested port.
2. Verify both callers resolve coherently to shared init outcome.
3. Run relay test suite.
### Expected
- No startup race flake for concurrent same-port init.
- Deterministic completion/failure propagation to all callers.
### Actual
- Verified by passing relay tests after patch.
## Evidence
- [x] Failing test/log before + passing after
- [ ] Trace/log snippets
- [ ] Screenshot/recording
- [ ] Perf numbers (if relevant)
## Human Verification (required)
- Verified scenarios: extension relay concurrent init behavior.
- Edge cases checked: same-port concurrent startup path.
- What you did **not** verify: full browser-extension E2E across all platforms.
## Compatibility / Migration
- Backward compatible? (`Yes`)
- Config/env changes? (`No`)
- Migration needed? (`No`)
- If yes, exact upgrade steps: `N/A`
## Failure Recovery (if this breaks)
- How to disable/revert this change quickly: revert this PR commits.
- Files/config to restore: browser relay files touched in this PR.
- Known bad symptoms reviewers should watch for: relay startup hangs or inconsistent concurrent startup outcomes.
## Risks and Mitigations
- Risk: Shared init promise lifecycle bug could stall startup in edge cases.
- Mitigation: explicit resolve/reject path and test coverage on concurrent startup scenario.
<!-- greptile_comment -->
<h3>Greptile Summary</h3>
Added shared promise coordination to deduplicate concurrent relay initialization on the same port. When multiple callers attempt to start a relay server simultaneously, subsequent callers now await the shared initialization promise instead of creating race conditions. The implementation properly handles both success and error propagation to all waiting callers, with cleanup guaranteed via finally blocks.
<h3>Confidence Score: 5/5</h3>
- This PR is safe to merge with minimal risk
- Clean implementation of concurrent initialization deduplication with proper error handling, cleanup logic, and test coverage. The promise coordination pattern correctly leverages JavaScript's single-threaded event loop to prevent races. No breaking changes or risky refactoring.
- No files require special attention
<sub>Last reviewed commit: 50342e0</sub>
<!-- greptile_other_comments_section -->
<!-- /greptile_comment -->
Most Similar PRs
#21314: feat: enhance browser relay with custom naming and diagnostic tools
by kelvinCB · 2026-02-19
79.1%
#20688: fix(browser): allow extension reconnect when stale websocket linger...
by HOYALIM · 2026-02-19
76.2%
#22571: fix(browser): complete extension relay handshake on connect.challenge
by pandego · 2026-02-21
76.1%
#17588: fix(relay): survive WS disconnects and MV3 worker restarts
by Unayung · 2026-02-15
76.0%
#20471: fix: share relay auth state across bundler chunks via globalThis
by MisterGuy420 · 2026-02-19
75.1%
#23363: Browser: fallback to managed profile and improve runtime diagnostics
by isdoho · 2026-02-22
72.9%
#16689: browser: support multiple Chrome extension connections to relay
by globalcaos · 2026-02-15
72.7%
#15817: fix(chrome-relay): auto-reconnect, MV3 persistence, and keepalive
by derrickburns · 2026-02-13
71.7%
#22252: fix(chrome-extension): connection validation and clarify relay port...
by krizpoon · 2026-02-20
71.5%
#16743: fix: auto-reattach browser relay debugger after navigation
by jg-noncelogic · 2026-02-15
71.1%