ActiveRecord :: RecordNotFound raises 404 instead of 500

We had an action that essentially failed in production because it raised an error ActiveRecord::RecordNotFound

that Rails treats as a 404 error instead of a 500 error, meaning it was not captured by our error logger.

I don't like that Rails displays certain errors on 404s. I think the developer needs to decide if the url is invalid or the error getting the record is an application error.

How do we ensure that all Rails bugs are treated as 500 bugs?

+3


source to share


2 answers


First of all, if you can manually report the error to the error, this is probably best. Rails' creation returns a different HTTP status code that can break other parts of your application.

However, if you absolutely must do so, you can tell Rails not to return a 404 by removing the corresponding entry from the rescue response hash. You can do this in the initializer:

# config/initializers/rescue_responses_overrides.rb
ActionDispatch::ExceptionWrapper.rescue_responses
  .delete('ActiveRecord::RecordNotFound')

      

Rails will now send a 500 status code to the browser on every promotion ActiveRecord::RecordNotFound

. You can also delete all entries in one step:



ActionDispatch::ExceptionWrapper.rescue_responses.clear

      

To see what other errors Rails returns different status codes, you can simply print the hash in the Rails console:

pp ActionDispatch::ExceptionWrapper.rescue_responses

      

+9


source


it was raising an ActiveRecord :: RecordNotFound error, which Rails treats as a 404 error instead of a 500 error

Right. Imagine that a search crawler hits your blog app and receives an error message in your non-existent blog post. If you come back 500

, the crawler will try to visit the page again later. If you go back 404

, the crawler will know the page is missing and will probably stop trying. Some browsers even display a custom embedded page if the server responds 500

.

If you still want to proceed, you have several options. You can rescue_from

in your top controller and change the answer to whatever you want.



class ApplicationController < ActionController::Base
  rescue_from ActiveRecord::RecordNotFound, OtherError do |exception|
    render nothing: true, status: 500 # nothing, redirect or a template
  end
end

      

Another option is to use a custom one exceptions_app

. It is basically a rack application that gets called when an exception is thrown and you can do whatever you want with a request / response. You can take a look at the default ( ActionDispatch::PublicExceptions

) implementation for inspiration.

+9


source







All Articles