teamcapybara/capybara · error · Capybara::WindowError

Could not find a window matching block/lambda

Error message

Could not find a window matching block/lambda

What it means

After the locator block fails on every open window, _switch_to_window_by_locator raises Capybara::WindowError: 'Could not find a window matching block/lambda'. Because the scan runs inside synchronize_windows, the entire iteration retries until the wait budget expires - so this error means no window ever satisfied the predicate within the wait, not merely that it was slow.

Source

Thrown at lib/capybara/session.rb:943

      else
        synchronize_windows(options) do
          original_window_handle = driver.current_window_handle
          begin
            _switch_to_window_by_locator(&window_locator)
          rescue StandardError
            driver.switch_to_window(original_window_handle)
            raise
          end
        end
      end
    end

    def _switch_to_window_by_locator
      driver.window_handles.each do |handle|
        driver.switch_to_window handle
        return Window.new(self, handle) if yield
      end
      raise Capybara::WindowError, 'Could not find a window matching block/lambda'
    end

    def synchronize_windows(options, &block)
      wait_time = Capybara::Queries::BaseQuery.wait(options, config.default_max_wait_time)
      document.synchronize(wait_time, errors: [Capybara::WindowError], &block)
    end
  end
end

View on GitHub (pinned to 15b5fdb76e)

Solutions

  1. Raise the wait: switch_to_window(wait: 5) { title == 'Dashboard' }
  2. Fix the predicate - prefer a url substring (current_url.include?('/chat')) over exact title match
  3. Debug what actually exists: page.windows.map { |w| [w.title, w.url] }.inspect
  4. If the window may have been closed, guard on page.driver.window_handles.size first

Example fix

# before
switch_to_window { title == 'Chat' } # WindowError: no match

# after
switch_to_window(wait: 10) { current_url.include?('/chat') }
Defensive patterns

Strategy: retry

Validate before calling

target = page.windows.find { |w| w.url.include?('/chat') }
switch_to_window(target) if target

Try / catch

begin
  switch_to_window { title == 'Chat' }
rescue Capybara::WindowError
  raise "no window matched; open windows: #{page.windows.map { |w| [w.title, w.url] }.inspect}"
end

Prevention

When it happens

Trigger: switch_to_window { title == 'Dashboard' } when no window has that exact title (SPA sets document.title asynchronously, typo, page still loading past the wait); matching on the wrong attribute (title vs url); the target window closed before the switch.

Common situations: SPA titles that render late; exact-title predicates breaking after rebranding or label changes; default_max_wait_time too low on CI; OAuth popups auto-closing before the predicate runs.

Related errors


AI-assisted analysis of teamcapybara/capybara@15b5fdb76e (2026-08-21). Data as JSON: /api/errors/daa5c22960284b61. Report an issue: GitHub.