{"record":{"id":"cc2345722290224d","repo":"teamcapybara/capybara","slug":"switch-to-frame-top-cannot-be-called-from-insi","errorCode":null,"errorMessage":"`switch_to_frame(:top)` cannot be called from inside a descendant frame's `within` block.","messagePattern":"`switch_to_frame\\(:top\\)` cannot be called from inside a descendant frame's `within` block\\.","errorType":"exception","errorClass":"Capybara::ScopeError","httpStatus":null,"severity":"error","filePath":"lib/capybara/session.rb","lineNumber":425,"sourceCode":"    #\n    def switch_to_frame(frame)\n      case frame\n      when Capybara::Node::Element\n        driver.switch_to_frame(frame)\n        scopes.push(:frame)\n      when :parent\n        if scopes.last != :frame\n          raise Capybara::ScopeError, \"`switch_to_frame(:parent)` cannot be called from inside a descendant frame's \" \\\n                                      '`within` block.'\n        end\n        scopes.pop\n        driver.switch_to_frame(:parent)\n      when :top\n        idx = scopes.index(:frame)\n        top_level_scopes = [:frame, nil]\n        if idx\n          if scopes.slice(idx..).any? { |scope| !top_level_scopes.include?(scope) }\n            raise Capybara::ScopeError, \"`switch_to_frame(:top)` cannot be called from inside a descendant frame's \" \\\n                                        '`within` block.'\n          end\n          scopes.slice!(idx..)\n          driver.switch_to_frame(:top)\n        end\n      else\n        raise ArgumentError, 'You must provide a frame element, :parent, or :top when calling switch_to_frame'\n      end\n    end\n\n    ##\n    #\n    # Execute the given block within the given iframe using given frame, frame name/id or index.\n    # May not be supported by all drivers.\n    #\n    # @overload within_frame(element)\n    #   @param [Capybara::Node::Element]  frame element\n    # @overload within_frame([kind = :frame], locator, **options)","sourceCodeStart":407,"sourceCodeEnd":443,"githubUrl":"https://github.com/teamcapybara/capybara/blob/15b5fdb76e972e9623d5af2123ed3755594f9732/lib/capybara/session.rb#L407-L443","documentation":"switch_to_frame(:top) resets to the top-level document, but only when every scope from the outermost frame onward is a frame or nil. If a within scope sits inside the frame chain, the slice check fails and Capybara::ScopeError is raised rather than silently discarding that element scope.","triggerScenarios":"within_frame(el) { within('.modal') { switch_to_frame(:top) } } - after the :frame scope a within scope remains, so scopes.slice(idx..).any? { |s| ![:frame, nil].include?(s) } trips; likewise calling switch_to_frame(:top) from helpers already running inside a within block.","commonSituations":"Deeply nested frame + within page objects; attempts to 'escape everything' from inside scoped helpers; refactors that moved switch_to_frame calls into methods already inside within.","solutions":["Exit the within block (and any nested scoping) before calling switch_to_frame(:top)","Let within_frame blocks expire naturally - each block exit already returns one level toward the top","Restructure page objects so top-level resets happen at the top level, not inside scoped helpers"],"exampleFix":"# before\nwithin_frame(:css, 'iframe.editor') do\n  within('.canvas') do\n    switch_to_frame(:top) # Capybara::ScopeError\n  end\nend\n\n# after\nwithin_frame(:css, 'iframe.editor') do\n  within('.canvas') { click_button 'Done' }\nend # back at the top-level document automatically","handlingStrategy":"validation","validationCode":"scopes = page.send(:scopes)\nidx = scopes.index(:frame)\nat_frame_top_only = idx.nil? || scopes.slice(idx..).all? { |s| s.nil? || s == :frame }\n\nswitch_to_frame(:top) if at_frame_top_only","typeGuard":null,"tryCatchPattern":"begin\n  switch_to_frame(:top)\nrescue Capybara::ScopeError => e\n  raise \"a `within` block is open inside the frame - close it first (#{e.message})\"\nend","preventionTips":["Avoid manual :top resets inside scoped code; rely on within_frame block exits","Keep a single owner of frame state per page object"],"tags":["frames","scope","within","switch-to-frame"],"backgroundTag":"invalid-frame-scope","analyzedSha":"15b5fdb76e972e9623d5af2123ed3755594f9732","analyzedAt":"2026-08-21T16:53:45.588Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}