teamcapybara/capybara · error · Capybara::ScopeError

Window cannot be switched inside a `within_frame` block

Error message

Window cannot be switched inside a `within_frame` block

What it means

_switch_to_window is the internal switcher shared by switch_to_window and within_window. It refuses to run while any frame scope is on the stack (scopes.include?(:frame)), raising Capybara::ScopeError because frame and window switches cannot compose - switching windows would strand the frame scope.

Source

Thrown at lib/capybara/session.rb:919

    def _find_frame(*args, **kw_args)
      case args[0]
      when Capybara::Node::Element
        args[0]
      when String, nil
        find(:frame, *args, **kw_args)
      when Symbol
        find(*args, **kw_args)
      when Integer
        idx = args[0]
        all(:frame, minimum: idx + 1)[idx]
      else
        raise TypeError
      end
    end

    def _switch_to_window(window = nil, **options, &window_locator)
      raise Capybara::ScopeError, 'Window cannot be switched inside a `within_frame` block' if scopes.include?(:frame)
      raise Capybara::ScopeError, 'Window cannot be switched inside a `within` block' unless scopes.last.nil?

      if window
        driver.switch_to_window(window.handle)
        window
      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

View on GitHub (pinned to 15b5fdb76e)

Solutions

  1. Finish the within_frame block first, then switch windows at the top level
  2. If a click inside the frame opens the window, return from the frame block before calling window_opened_by/switch_to_window
  3. Design page objects so frame and window contexts never overlap

Example fix

# before
within_frame('chat') do
  switch_to_window(other_window) # Capybara::ScopeError
end

# after
within_frame('chat') { click_link 'Open dashboard' }
switch_to_window(other_window)
Defensive patterns

Strategy: validation

Validate before calling

switch_to_window(other_window) unless page.send(:scopes).include?(:frame)

Try / catch

begin
  switch_to_window(w)
rescue Capybara::ScopeError => e
  raise "exit the within_frame block before switching windows (#{e.message})"
end

Prevention

When it happens

Trigger: within_frame('chat') { switch_to_window(other_window) }; within_frame { within_window(-> { title == 'X' }) { ... } }; page-object frame helpers that switch windows before the frame block exits.

Common situations: Flows that open popups from inside iframes (payment/SSO frames); page objects nesting within_frame that also manage windows; refactors moving window code into frame-scoped helpers.

Related errors


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