I'm another developer who worked on this with @jason328. It turned out to be a multi-part problem, first with general 422 errors, and then with the specific scenario in which Rails was raising ActiveRecord::InvalidAuthenticityToken
and not rendering the appropriate page.
1. General 422 Errors
The Rails error page
We got rid of this temporarily in our local development environment by setting config.consider_all_requests_local = false
. But then instead of getting our custom error page, we got a blank white page.
The blank white page
As per this Stack Overflow question, we needed match '/422', to: 'errors#unprocessable_entity', via: :all
for the route instead of get '/422' => 'errors#unprocessable_entity'
.
At this point, generic 422 errors performed as they should. We set up a controller action that raised ActiveRecord::InvalidAuthenticityToken
as soon as you hit it, and it rendered our custom 422 page. So for anyone just having trouble with 422 errors in general, the above should cover you.
2. InvalidAuthenticityToken
But since a common cause of 422 errors is actually getting an InvalidAuthenticityToken
error in the wild, it seems worth describing the rest of the problem we were seeing. In the actual scenario where the app was generating its own InvalidAuthenticityToken
error, we were now getting a text-only 500 error, instead of our custom 422 page.
Text-only 500 error
We were able to trace this to the FAILSAFE_RESPONSE
in ActionDispatch::ShowExceptions#render_exception
. This is where Rails takes the exception that's been thrown and converts it to a [status, body, headers]
response array. If another exception gets thrown during that time, rather than getting caught in an endless loop, it gives up and returns the FAILSAFE_RESPONSE. In this case, another InvalidAuthenticityToken
error was getting thrown while putting together the response.
At this point, it was time for the :rescue_from
strategy:
rescue_from ActionController::InvalidAuthenticityToken,
with: :rescue_invalid_authenticity_token
def rescue_invalid_authenticity_token
#...notify services as if this error weren't being rescued
redirect_to '/422'
end
with a redirect to keep us safe from any more InvalidAuthenticityToken
errors in the same request.