{"record":{"id":"df2b8f6de091b861","repo":"rails/rails","slug":"response-is-a-redirection","errorCode":null,"errorMessage":"Response is a redirection!","messagePattern":"Response is a redirection!","errorType":"exception","errorClass":"ActionDispatch::TestHelpers::PageDumpHelper::InvalidResponse","httpStatus":null,"severity":"warning","filePath":"actionpack/lib/action_dispatch/testing/test_helpers/page_dump_helper.rb","lineNumber":16,"sourceCode":"# frozen_string_literal: true\n\nmodule ActionDispatch\n  module TestHelpers\n    module PageDumpHelper\n      class InvalidResponse < StandardError; end\n\n      # Saves the content of response body to a file and tries to open it in your browser.\n      # Launchy must be present in your Gemfile for the page to open automatically.\n      def save_and_open_page(path = html_dump_default_path)\n        save_page(path).tap { |s_path| open_file(s_path) }\n      end\n\n      private\n        def save_page(path = html_dump_default_path)\n          raise InvalidResponse.new(\"Response is a redirection!\") if response.redirection?\n          path = Pathname.new(path)\n          path.dirname.mkpath\n          File.write(path, response.body)\n          path\n        end\n\n        def open_file(path)\n          require \"launchy\"\n          Launchy.open(path)\n        rescue LoadError\n          warn \"File saved to #{path}.\\nPlease install the launchy gem to open the file automatically.\"\n        end\n\n        def html_dump_default_path\n          Rails.root.join(\"tmp/html_dump\", \"#{method_name}_#{DateTime.current.to_i}.html\").to_s\n        end\n    end\n  end","sourceCodeStart":1,"sourceCodeEnd":34,"githubUrl":"https://github.com/rails/rails/blob/2c224ba8f22074b7ffa465dead412b78163fe152/actionpack/lib/action_dispatch/testing/test_helpers/page_dump_helper.rb#L1-L34","documentation":"Raised as ActionDispatch::TestHelpers::PageDumpHelper::InvalidResponse from save_page (the private engine behind save_and_open_page) when response.redirection? is true. The helper writes response.body to an HTML file to open in a browser, but a 3xx redirect has an empty/Location-only body unsuitable for inspection, so it refuses rather than write a misleading dump.","triggerScenarios":"In a request/integration test, calling save_and_open_page (or save_page) right after an action that issued redirect_to — e.g. a successful create action that redirects to show. The test asserts follow_redirect! was not called, so the response is still the 302.","commonSituations":"Debugging a controller test where you expected a render but got a redirect; calling save_and_open_page inside a block before follow_redirect!; integration test that hits a before_action redirecting for auth.","solutions":["Call follow_redirect! before save_and_open_page to land on the final rendered page.","If you intended a render, fix the controller (remove the redirect_to, or assert the redirect is wrong).","To inspect the redirect itself, assert response.status / response.location instead of dumping the body.","For multi-step flows, use the integration session's follow_redirect! repeatedly until response.redirection? is false."],"exampleFix":"# before\npost posts_path, params: { post: attrs }\nsave_and_open_page   # raises: response is a 302\n\n# after\npost posts_path, params: { post: attrs }\nfollow_redirect!\nsave_and_open_page   # now dumps the rendered show page","handlingStrategy":"validation","validationCode":"# In tests, follow redirects before dumping.\ndef dump_after_follow\n  follow_redirect! while response.redirection?\n  save_and_open_page\nend","typeGuard":"# @return [Boolean] response is dumpable (not a redirect)\ndef dumpable_response?\n  response&.response_code && !response.redirection?\nend","tryCatchPattern":"# Not really rescuable in a useful way; just guard:\nsave_and_open_page unless response.redirection?","preventionTips":["Always follow_redirect! before save_and_open_page.","If a redirect is unexpected, assert response.status first to pin the cause.","Use save_and_open_page only on rendered (2xx) responses.","Prefer assert_select / assert_response over visual dumps in CI."],"tags":["actionpack","test","debugging","redirect"],"backgroundTag":null,"analyzedSha":"2c224ba8f22074b7ffa465dead412b78163fe152","analyzedAt":"2026-08-10T19:11:06.792Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}