Question

If we request a bogus image file, Rails generates an internal 500 server error instead of a 404. See the log below.

Here is the line in routes.rb that catches 404s:

# Catches all 404 errors and redirects
match '*url' => 'default#error_404'

Other unknown URLs are handled correctly with 404s. What is different for image files and URLs with file extensions?

Started GET "/images/doesnotexistyo.png" for 71.198.44.101 at 2013-03-08 07:59:24 +0300
Processing by DefaultController#error_404 as PNG
  Parameters: {"url"=>"images/doesnotexistyo"}
Completed 500 Internal Server Error in 1ms

ActionView::MissingTemplate (Missing template default/error_404, application/error_404 with {:locale=>[:en], :formats=>[:png], :handlers=>[:erb, :builder]}. Searched in:
  * "/home/prod/Prod/app/views"
Was it helpful?

Solution

The problem is that the error_404 method inside the Default controller can't handle requests in png format. When you ask for say, a JSON response, you could build an URL similar to:

/controller/action.json

And inside the action you would have something like

def action
  respond_to do |format|
    format.html # Renders the default view
    format.json { render :json => @model }
    format.xml { render :xml => @model }
  end
end

As you can see, it's specified how to handle a JSON and an XML request, but since there's no format.png, the action can't handle the .png format. Add this:

format.png # Handle the request here...

Hope it helps :)

Edit

Add this to redirect to your 404 handler:

def error_404
  respond_to do |format|
    format.html
    format.png { redirect_to :controller => 'default', :action => 'error_404' }
  end
end

Cheers :)

Edit2

Use this code to catch all kinds of requests:

def error_404
  respond_to do |format|
    format.html { render :not_found_view }
    format.all { redirect_to controller: 'default', action: 'error_404' }
  end
end

Replace :not_found_view with your 404 page. This will render the 404 page for html requests, and redirect to self (with html format) for any other kind of request.

Hope it helps :)

OTHER TIPS

What is DefaultController? That controller is dealing with the 404, instead of Rails default response:

ActionController::RoutingError (No route matches [GET] "/images/doesnotexistyo.png"):

So find out this controller, error_404 is being executed and no template default/error_404 was found, hence the 500 error.

You probably have a code similar to this somewhere in your code:

rescue_from ActiveRecord::RecordNotFound, :with => :error_404

Maybe not for you, but since I do some final checks for pages dynamically in my controllers, I just follow all my 404'ing with one to handle non-html files:

format.all { render :status => 404, :nothing => true }
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top