{"record":{"id":"44da23cc33dfb4d4","repo":"teamcapybara/capybara","slug":"redirected-more-than-driver-redirect-limit-time","errorCode":null,"errorMessage":"redirected more than #{driver.redirect_limit} times, check for infinite redirects.","messagePattern":"redirected more than #(.+?) times, check for infinite redirects\\.","errorType":"exception","errorClass":"Capybara::InfiniteRedirectError","httpStatus":null,"severity":"error","filePath":"lib/capybara/rack_test/browser.rb","lineNumber":70,"sourceCode":"  end\n\n  def process_and_follow_redirects(method, path, attributes = {}, env = {})\n    @current_fragment = build_uri(path).fragment\n    process(method, path, attributes, env)\n    return unless driver.follow_redirects?\n\n    driver.redirect_limit.times do\n      if last_response.redirect?\n        if [307, 308].include? last_response.status\n          process(last_request.request_method, last_response['Location'], last_request.params, env)\n        else\n          process(:get, last_response['Location'], {}, env)\n        end\n      end\n    end\n\n    if last_response.redirect? # rubocop:disable Style/GuardClause\n      raise Capybara::InfiniteRedirectError, \"redirected more than #{driver.redirect_limit} times, check for infinite redirects.\"\n    end\n  end\n\n  def process(method, path, attributes = {}, env = {})\n    method = method.downcase\n    new_uri = build_uri(path)\n    @current_scheme, @current_host, @current_port = new_uri.select(:scheme, :host, :port)\n    @current_fragment = new_uri.fragment || @current_fragment\n    reset_cache!\n    @new_visit_request = false\n    send(method, new_uri.to_s, attributes, env.merge(options[:headers] || {}))\n  end\n\n  def build_uri(path)\n    uri = URI.parse(path)\n    base_uri = base_relative_uri_for(uri)\n\n    uri.path = base_uri.path + uri.path unless uri.absolute? || uri.path.start_with?('/')","sourceCodeStart":52,"sourceCodeEnd":88,"githubUrl":"https://github.com/teamcapybara/capybara/blob/15b5fdb76e972e9623d5af2123ed3755594f9732/lib/capybara/rack_test/browser.rb#L52-L88","documentation":"The rack_test browser follows HTTP redirects up to driver.redirect_limit times (default 5, see DEFAULT_OPTIONS in lib/capybara/rack_test/driver.rb). 307/308 redirects replay the original method with params; other redirects become GET. If the response is still a redirect after the full budget, Capybara raises Capybara::InfiniteRedirectError. It means either the app is genuinely looping or the chain legitimately exceeds 5 hops.","triggerScenarios":"visit '/login' under the rack_test driver where the Rack app responds 302 -> 302 -> ... forever (e.g. session cookie dropped each hop because the host changes, or a before_action bounces between / and /en); or a valid A->B->C->D->E->F chain of 6 redirects with the default redirect_limit: 5.","commonSituations":"Rack::Test not sending cookies after a redirect to a different host/port in the test environment; Rails force_ssl or host-canonicalization middleware ping-ponging in test config; omniauth/callback flows with long redirect chains under the default limit; an actual app regression that only manifests in integration tests.","solutions":["Reproduce the loop outside Capybara (curl -v or a bare Rack::Test session) and fix the app-side cause - most often the session cookie is lost because the redirect changes host, so pin the test host (e.g. Rack::Test::Session host or Rails default_url_options / Capybara.app_host).","If the chain is legitimately long, raise the limit by registering the driver yourself: Capybara::RackTest::Driver.new(app, redirect_limit: 10).","Check middleware order for redirect loops (SSL, locale, authentication redirects referencing each other).","If the redirect depends on JavaScript (location.href), rack_test cannot execute it - move the spec to a JS driver."],"exampleFix":"# before\nCapybara.register_driver :rack_test do |app|\n  Capybara::RackTest::Driver.new(app)\nend\n\n# after\nCapybara.register_driver :rack_test do |app|\n  Capybara::RackTest::Driver.new(app, redirect_limit: 10)\nend","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"begin\n  visit '/start'\nrescue Capybara::InfiniteRedirectError => e\n  save_and_open_page # or log last_response status/Location chain\n  raise\nend","preventionTips":["Keep redirect chains under the configured limit in test routes; raise redirect_limit via Capybara::RackTest::Driver.new(app, redirect_limit: N) only for genuinely long chains.","Pin a single test host (Capybara.app_host / Rack test host) so session cookies survive every hop.","Reproduce suspected loops with curl -v before blaming Capybara."],"tags":["ruby","capybara","rack-test","redirects","http"],"backgroundTag":"infinite-redirect-loop","analyzedSha":"15b5fdb76e972e9623d5af2123ed3755594f9732","analyzedAt":"2026-08-21T16:53:45.588Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}