BrowserError when calling `browser.reset` after initializing browser while using browserless v2
Describe the bug A clear and concise description of what the bug is.
Ferrum v0.17 introduced a bug where calling browser.reset immediately after initializing a new Browser instance causes an Failed to find context with id 02B3B5EFF6A3105729C7F971F1B93E67 (Ferrum::BrowserError). Ferrum v0.16 does not have this issue, and I have been so far unable to identify which change from v0.16 has caused this.
To Reproduce Steps to reproduce the behavior, a failing test or a debug log.
require 'ferrum'
browser = Ferrum::Browser.new(ws_url: "ws://browserless:3000")
browser.reset
Expected behavior A clear and concise description of what you expected to happen.
browser.reset should work without errors, it appears the default browser context that ferrum is setting is invalid.
Screenshots If applicable, add screenshots to help explain your problem.
note: in this example port is 3333 not 3000 as I was running browserless with that port.
Desktop (please complete the following information):
- OS: Linux
- Browser: ghcr.io/browserless/chromium:latest
- Version: Ruby 3.3.7 and Ferrum v0.17.1
Additional context Add any other context about the problem here.
I encounter this issue as I am using Cuprite v0.17.1 with capybara and it calls browser.reset after each test.
Just wanted to give an update that passing flatten: false to Ferrum::Browser.new or Capybara::Cuprite::Driver.new, causes the error about the missing context to go away, when using ferrum/cuprite with browserless 2 on v0.17.0 and v.017.1
I believe the regression is due to two factors:
-
In 2020 browserless/browserless commit 4dd97bd removed a session filter (
.filter(({ title }) => title !== 'about:blank')for more transparency. -
Then, on April 30th, 2025 (v0.17.0), in rubycdp/ferrum commit cca9a0d, this block was added for contexts not present in the Concurrent::Map:
unless @contexts[context_id]
context = Context.new(@client, self, context_id)
@contexts[context_id] = context
@default_context ||= context
end
The issue is when Ferrum attaches to a target where the URL is "about:blank". The context is added, but when the session is reset, each context is disposed. When Ferrum commands browserless @client.command("Target.disposeBrowserContext", browserContextId: context.id, that's when you'll receive the Ferrum::BrowserError "Failed to find context with id...". The missing context id is Chrome's "about:blank" target.
I think maybe on the client event Target.attachedToTarget, we should break early if the url is 'about:blank'.
module Ferrum
class Contexts
ALLOWED_TARGET_TYPES = %w[page iframe].freeze
+ ABOUT_BLANK = "about:blank".freeze
...
@client.on("Target.attachedToTarget") do |params|
info, session_id = params.values_at("targetInfo", "sessionId")
next unless ALLOWED_TARGET_TYPES.include?(info["type"])
+ next if ABOUT_BLANK == info['url']
....
Commenting out the unless block, adding the guard clause, or setting flatten: false all seem to be valid workarounds for me.
Another solution might be handle the exception on #dispose in case there's any value in the about:blank context being registered.
def dispose(context_id)
context = @contexts[context_id]
context.close_targets_connection
begin
@client.command("Target.disposeBrowserContext", browserContextId: context.id)
rescue NoExecutionContextError
warn "Browser context #{context.id} was already disposed" unless context.page&.url == ABOUT_BLANK
ensure
@contexts.delete(context_id)
end
true
end
And expand the case for a NoExecutionContextError like so:
when "Cannot find context with specified id", /Failed to find context with id/
raise NoExecutionContextError, error