Error handling

Mike edited this page Mar 2, 2014 · 2 revisions

Part of a good user experience is recovering gracefully when something goes wrong. The basic principles of Concerto error handling will be that similar types of errors are consistent across the application, that errors appropriately express what's gone wrong and offer a way to fix it, and that errors do not reveal information about the application's data or state that could aid an attacker.

Errors and the Environment

When developing and testing error-handling code, keep in mind that a few variables may affect how errors are rendered:

  • Environment - Error handling is very different in development mode versus production mode. In development mode, errors include detailed debugging information and a stack trace. Production mode is where we actually get to the error handling and need to display a good error page to the user.
  • Server type - Concerto is generally served by one of two types of servers - a server that is dedicated to Concerto (Thin, Unicorn, etc.) or a general-purpose server, such as Nginx or Apache running Passenger, that calls Concerto as a rack environment. The difference between these two environments is that if the application fails to boot, for example a failed dependency or a major syntax error, the dedicated server will simply fail to start, whereas Passenger will serve out an error page.

Error Types

URL Errors

We need to test several different classes of URL errors, because they are all handled differently in rails.

  • No route matches. For example, http://concerto.example.com/asdfasdf.
  • Appropriate response: Error page with status HTTP 404/Not Found
  • Record not found / some dynamic object does not exist. For example, http://concerto.example.com/screens/999
  • Appropriate response: Error page with status HTTP 404/Not Found
  • Invalid type requested. For example, http://concerto.example.com/screens.doc - this matches a valid route but Concerto doesn't know how to respond.
  • Current response: a totally blank page (with status HTTP 406/Not Acceptable)
  • Better response: 404?
  • Note: an added variable in this situation is the Accept: header sent by the client, which can affect what format Rails decides to use.

Authorization Errors

For pages that a user doesn't have permission to see, we need to render a

An important consideration for review should be whether these can unintentionally leak data from the app. For example, by trying URLs such as /users/1, /users/2, and so on, a logged out user on a non-public instance can figure out how many users there are by seeing when the app stops serving 403s and starts serving 404s. This may seem minor but some information may be worth protecting.

How we respond - the CanCan auth logic, or any part of the app, may simply raise the appropriate error (CanCan::AccessDenied). This will be caught and handled by logic in ApplicationController.

The current behavior is to issue a redirect with HTTP Status 302/Found to the application root and display an Alert banner upon arrival.

It's important to keep in mind that the application should never present a link to take someone to a page they can't access. In general, these errors occur when someone types in an incorrect URL,

Mike's preferred behavior would look like this:

  • For users who are not signed in, prompt them to log in, and return them to the page they tried to access.
  • For other users, alert them to the error, reminding who they are signed in as. Provide links to go back and/or to the application root.

Application errors

Application errors come in two general flavors: errors booting the app, and exceptions raised while running the app. The latter could result from anything between a syntax error and a totally broken branch of code somewhere. But it means something is very wrong with the application, and the general goal should be that a user can't trigger a 500 no matter what they do.

In general, these should return the 500 error page with the HTTP 500/Internal Server Error status.

How we respond - In development mode, this errors will appear with a full stack trace. In production, they get intercepted. By default, they're routed to the PublicExceptions rack app which in turn looks for 500.html.

Problem areas:

  • We want to get back to rendering the 404s and 500s in app, with full templates, if possible
  • Blank 406s seem bad
  • Figure out how to respond for non-html formats
  • Path of several redirects when going to /feeds (that is, clicking "browse in the menu") in a non-public Concerto instance
  • Consider different behavior for 403s.