{"record":{"id":"d5dc86f0b9a1d1fb","repo":"teamcapybara/capybara","slug":"switch-to-frame-parent-cannot-be-called-from-i","errorCode":null,"errorMessage":"`switch_to_frame(:parent)` cannot be called from inside a descendant frame's `within` block.","messagePattern":"`switch_to_frame\\(:parent\\)` 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":415,"sourceCode":"    # If you use this method you are responsible for making sure you switch back to the parent frame when done in the frame changed to.\n    # {#within_frame} is preferred over this method and should be used when possible.\n    # May not be supported by all drivers.\n    #\n    # @overload switch_to_frame(element)\n    #   @param [Capybara::Node::Element] element    iframe/frame element to switch to\n    # @overload switch_to_frame(location)\n    #   @param [Symbol] location relative location of the frame to switch to\n    #                            * :parent - the parent frame\n    #                            * :top - the top level document\n    #\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","sourceCodeStart":397,"sourceCodeEnd":433,"githubUrl":"https://github.com/teamcapybara/capybara/blob/15b5fdb76e972e9623d5af2123ed3755594f9732/lib/capybara/session.rb#L397-L433","documentation":"switch_to_frame(:parent) is only valid when the innermost scope is a frame (scopes.last == :frame). Calling it while a within block is active - even one nested inside a frame - raises Capybara::ScopeError, because popping to the parent frame would silently escape the element scope the block established.","triggerScenarios":"within_frame(el) { within('.toolbar') { switch_to_frame(:parent) } } - the innermost scope is the within scope, not :frame; also any manual switch_to_frame(:parent) issued from page-object methods invoked inside a within block.","commonSituations":"Page objects mixing within with manual frame navigation; refactoring from the looser Capybara 1.x frame API; copy-pasting frame-navigation helpers into scoped contexts.","solutions":["Close the enclosing within block before calling switch_to_frame(:parent)","Prefer the within_frame(el) { ... } block form, which returns to the parent frame automatically at block exit","To escape all frames, exit every within block first and use switch_to_frame(:top)"],"exampleFix":"# before\nwithin_frame(:css, 'iframe.chat') do\n  within('.composer') do\n    switch_to_frame(:parent) # Capybara::ScopeError\n  end\nend\n\n# after\nwithin_frame(:css, 'iframe.chat') do\n  within('.composer') { fill_in 'Message', with: 'hi' }\nend # frame scope restored automatically, no manual switch needed","handlingStrategy":"validation","validationCode":"switch_to_frame(:parent) if page.send(:scopes).last == :frame","typeGuard":null,"tryCatchPattern":"begin\n  switch_to_frame(:parent)\nrescue Capybara::ScopeError => e\n  raise \"still inside a `within` block - restructure before popping frames (#{e.message})\"\nend","preventionTips":["Use within_frame's block form instead of manual switch_to_frame","Never call switch_to_frame from inside within; end the scoped block first"],"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"}