{"record":{"id":"50e74c7db2469f2f","repo":"teamcapybara/capybara","slug":"you-must-provide-a-frame-element-parent-or-top","errorCode":null,"errorMessage":"You must provide a frame element, :parent, or :top when calling switch_to_frame","messagePattern":"You must provide a frame element, :parent, or :top when calling switch_to_frame","errorType":"exception","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"lib/capybara/session.rb","lineNumber":432,"sourceCode":"        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)\n    #   @param [Symbol] kind      Optional selector type (:frame, :css, :xpath, etc.) - Defaults to :frame\n    #   @param [String] locator   The locator for the given selector kind.  For :frame this is the name/id of a frame/iframe element\n    # @overload within_frame(index)\n    #   @param [Integer] index         index of a frame (0 based)\n    def within_frame(*args, **kw_args)\n      switch_to_frame(_find_frame(*args, **kw_args))\n      begin","sourceCodeStart":414,"sourceCodeEnd":450,"githubUrl":"https://github.com/teamcapybara/capybara/blob/15b5fdb76e972e9623d5af2123ed3755594f9732/lib/capybara/session.rb#L414-L450","documentation":"switch_to_frame accepts exactly three argument kinds: a Capybara::Node::Element for a located frame, :parent, and :top. Anything else - a String frame name/id, an Integer index, nil - reaches the else branch and raises ArgumentError immediately, before any driver call.","triggerScenarios":"switch_to_frame('payment_iframe') (frame name as String); switch_to_frame(0) (index); switch_to_frame(nil); passing a locator string that would have worked with within_frame.","commonSituations":"Old Capybara 1.x habits where frame names were strings; reaching for switch_to_frame when within_frame(name_or_index) is the locating API; passing find results for non-frame elements.","solutions":["Use within_frame for locating by name/id/index: within_frame('payment_iframe') { ... } or within_frame(0) { ... }","If switching manually, find the element first: switch_to_frame(find(:frame, 'payment_iframe'))","Remember only :parent/:top symbols and frame elements are valid for the manual API"],"exampleFix":"# before\nswitch_to_frame('payment_iframe') # ArgumentError\n\n# after\nwithin_frame('payment_iframe') { fill_in 'Card number', with: '4242' }\n# or manual:\nswitch_to_frame(find(:frame, 'payment_iframe'))","handlingStrategy":"type-guard","validationCode":"switch_to_frame(find(:frame, 'payment_iframe')) if 'payment_iframe'.is_a?(String)","typeGuard":"def frame_target?(arg)\n  arg.is_a?(Capybara::Node::Element) || %i[parent top].include?(arg)\nend\n\nswitch_to_frame(arg) if frame_target?(arg)","tryCatchPattern":"begin\n  switch_to_frame(arg)\nrescue ArgumentError\n  within_frame(arg) { yield } # fall back to the locating API\nend","preventionTips":["Use within_frame for name/index/element addressing","Reserve switch_to_frame for manual :parent/:top navigation with already-found elements"],"tags":["frames","argument-validation","switch-to-frame","api-misuse"],"backgroundTag":"invalid-argument-value","analyzedSha":"15b5fdb76e972e9623d5af2123ed3755594f9732","analyzedAt":"2026-08-21T16:53:45.588Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}