You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Fetch.enable ignores urlPattern patterns — intercepts every request and stalls navigation #5
Fetch.enable with a patterns array of urlPatterns is translated to Juggler's Browser.setRequestInterception with only {enabled: true} — the URL patterns are dropped entirely. As a result, every request in the browser is intercepted (paused) instead of only the requests matching the requested patterns.
Root cause
In pkg/bridge/fetch.go, the Fetch.enable handler parses params.Patterns but never uses it; it only forwards {"enabled": true} to Juggler. Juggler has no pattern support of its own, so the bridge must implement the pattern filtering — but it currently doesn't, and the Browser.requestIntercepted → Fetch.requestPaused handler in pkg/bridge/events.go emits a paused event for every intercepted request.
Impact
Any client that scopes Fetch.enable to a single URL (e.g. a dialog-bridge supervisor intercepting only http://hermes-dialog-bridge.invalid/*) gets all navigation requests paused forever:
Page.navigate returns a navigationId, but the page never commits — no frameNavigated is ever emitted.
Every request waits for a Fetch.continueRequest that the client will never send (it only handles requests matching its pattern).
Navigation stalls indefinitely; the only way out is disabling interception entirely.
Repro steps
Start foxbridge and connect a CDP client (e.g. Puppeteer) to a Firefox/Camoufox instance.
Call Fetch.enable with a single pattern, e.g. {"patterns": [{"urlPattern": "http://hermes-dialog-bridge.invalid/*"}]}.
Call Page.navigate to any other URL (e.g. https://example.com).
Observe: the navigation request is paused and Fetch.requestPaused is emitted for it (matching the pattern or not), Page.navigate returns a navigationId, but frameNavigated never fires and the page never loads.
Expected vs actual
Expected (Chrome semantics): only requests matching at least one urlPattern are paused; all other requests are transparently continued.
Actual: every request is paused and waits for a continuation that never comes.
Fix approach
Keep the per-CDP-session urlPattern list from Fetch.enable (and clear it on Fetch.disable).
In the Browser.requestIntercepted handler, auto-continue (Browser.continueInterceptedRequest) any request whose URL matches no pattern, and only emit Network.requestWillBeSent / Fetch.requestPaused for matching requests.
Pattern matching mirrors Chrome: glob where * matches any sequence, case-insensitive, anchored to the full URL.
Fetch.enable with no patterns keeps the current behavior (intercept everything).
Follow-up: root cause is deeper than urlPattern handling — PR #6 now carries the complete fix
While validating the pattern fix, we found that the interception stall is caused by two protocol-level bugs, not just the dropped patterns:
1. foxbridge uses Juggler methods/events that do not exist
Verified against the bundled protocol (omni.ja → chrome/juggler/content/protocol/):
Browser.requestIntercepted (subscribed in events.go) is not emitted by Juggler — the per-page NetworkObserver pauses requests and emits Network.requestWillBeSent with an isIntercepted flag (PageNetwork.Events.Request).
Browser.continueInterceptedRequest / Browser.setRequestInterception (browser-level) don't drive the page's interception — the real page-session methods are Network.setRequestInterception, Network.resumeInterceptedRequest, Network.fulfillInterceptedRequest, Network.abortInterceptedRequest.
So with Fetch.enable the request is genuinely paused in the browser (visible: Page.navigate returns navigationId but no frameNavigated ever commits) while the bridge never receives any interception event → deadlock.
PageHandler._handleNetworkEvent(event, details, frameId) holds network events in _networkEventsForUnreportedFrameIds until _reportedFrameIds.has(frameId). The helper.on dispatcher passes only (eventDetails) (frameId is never the 3rd argument), and the frame IDs themselves mismatch: Page.frameAttached reports a UUID (e90bdc68-…) while network events carry mainframe-N (from browsingContextToFrameId). The set lookup never matches → every Network.requestWillBeSent is buffered indefinitely, even without interception.
Fetch.requestPaused emitted from Network.requestWillBeSent when isIntercepted is set
urlPattern scoping retained: requests outside the pattern are auto-resumed
The Camoufox-side frameId/buffer issue (omni.ja) is a separate bug in the browser itself — on our side we patch PageHandler._handleNetworkEvent to emit events directly. Happy to open a separate issue for that one if useful.
Further verification against the Camoufox 135 bundle (omni.ja) proved the stall is not the dropped urlPatterns — it's that Juggler never delivers interception events at all:
Network.setRequestInterception({enabled: true}) (page session) makes the NetworkObserver pause requests (channelIntercepted → stored in _interceptedRequests awaiting resumeInterceptedRequest).
But PageNetwork.Events.Request is never delivered to the PageHandler (browser process): no Network.requestWillBeSent ever reaches the bridge — confirmed by zero occurrences in the full bridge log and by instrumenting the omni.ja handlers (the PageHandler's _handleNetworkEvent never fires; even the Camoufox-internal channelIntercepted probe stays silent while the navigation hangs).
Result: with Fetch enabled, every request is paused forever, nobody emits Fetch.requestPaused, nothing calls resumeInterceptedRequest → Page.navigate returns navigationId, frameNavigated never arrives. Fetch.disable (which resumes all _interceptedRequests) unblocks navigation — proving the pause is real.
Fix shipped:Fetch.enable is now a no-op (patterns still parsed/stored for a future Juggler fix). Navigation flows; dialog interception via Fetch is degraded but pages load. This unblocks every CDP client that enables Fetch (e.g. the Hermes dialog-bridge supervisor) and is verified end-to-end: Fetch.enable → Page.navigate → frameNavigated → page loads.
The earlier commits (patterns + Network.* rename) remain valid groundwork; the no-op is the safe behavior until Juggler starts delivering interception events.
Activity
lgwacker commentedon Aug 12, 2026
Follow-up: root cause is deeper than urlPattern handling — PR #6 now carries the complete fix
While validating the pattern fix, we found that the interception stall is caused by two protocol-level bugs, not just the dropped patterns:
1. foxbridge uses Juggler methods/events that do not exist
Verified against the bundled protocol (
omni.ja→chrome/juggler/content/protocol/):Browser.requestIntercepted(subscribed inevents.go) is not emitted by Juggler — the per-pageNetworkObserverpauses requests and emitsNetwork.requestWillBeSentwith anisInterceptedflag (PageNetwork.Events.Request).Browser.continueInterceptedRequest/Browser.setRequestInterception(browser-level) don't drive the page's interception — the real page-session methods areNetwork.setRequestInterception,Network.resumeInterceptedRequest,Network.fulfillInterceptedRequest,Network.abortInterceptedRequest.So with
Fetch.enablethe request is genuinely paused in the browser (visible:Page.navigatereturnsnavigationIdbut noframeNavigatedever commits) while the bridge never receives any interception event → deadlock.2. Camoufox PageHandler buffers network events forever (omni.ja)
PageHandler._handleNetworkEvent(event, details, frameId)holds network events in_networkEventsForUnreportedFrameIdsuntil_reportedFrameIds.has(frameId). Thehelper.ondispatcher passes only(eventDetails)(frameId is never the 3rd argument), and the frame IDs themselves mismatch:Page.frameAttachedreports a UUID (e90bdc68-…) while network events carrymainframe-N(frombrowsingContextToFrameId). The set lookup never matches → every Network.requestWillBeSent is buffered indefinitely, even without interception.Fixes shipped in PR #6 (commit 57ebbbc)
Fetch.enable/disable→Network.setRequestInterceptionon the page sessionFetch.continue/fulfill/failRequest→Network.resume/fulfill/abortInterceptedRequestFetch.requestPausedemitted fromNetwork.requestWillBeSentwhenisInterceptedis seturlPatternscoping retained: requests outside the pattern are auto-resumedThe Camoufox-side frameId/buffer issue (
omni.ja) is a separate bug in the browser itself — on our side we patchPageHandler._handleNetworkEventto emit events directly. Happy to open a separate issue for that one if useful.lgwacker commentedon Aug 12, 2026
Final root cause + fix update (commit a41f9e6)
Further verification against the Camoufox 135 bundle (
omni.ja) proved the stall is not the dropped urlPatterns — it's that Juggler never delivers interception events at all:Network.setRequestInterception({enabled: true})(page session) makes the NetworkObserver pause requests (channelIntercepted→ stored in_interceptedRequestsawaitingresumeInterceptedRequest).PageNetwork.Events.Requestis never delivered to the PageHandler (browser process): noNetwork.requestWillBeSentever reaches the bridge — confirmed by zero occurrences in the full bridge log and by instrumenting the omni.ja handlers (the PageHandler's_handleNetworkEventnever fires; even the Camoufox-internalchannelInterceptedprobe stays silent while the navigation hangs).Fetch.requestPaused, nothing callsresumeInterceptedRequest→Page.navigatereturnsnavigationId,frameNavigatednever arrives.Fetch.disable(which resumes all_interceptedRequests) unblocks navigation — proving the pause is real.Fix shipped:
Fetch.enableis now a no-op (patterns still parsed/stored for a future Juggler fix). Navigation flows; dialog interception via Fetch is degraded but pages load. This unblocks every CDP client that enables Fetch (e.g. the Hermes dialog-bridge supervisor) and is verified end-to-end:Fetch.enable→Page.navigate→frameNavigated→ page loads.The earlier commits (patterns +
Network.*rename) remain valid groundwork; the no-op is the safe behavior until Juggler starts delivering interception events.