Jump to content

Developer Documentation

Error Handling

Errors are a natural part of any web application, and you will need to be prepared to show errors when appropriate. Invision Community software has several powerful built in features for error handling that you should familiarize yourself with in order to best handle unexpected (or even expected, but invalid) situations.

The Invision Community software throws Exceptions when appropriate, and attempts to throw the most valid exception class possible (including custom exception classes that extend default PHP exception classes). This means that many times when you are calling built in methods within the suite, you will need to wrap those calls in try/catch statements. For instance, when making an HTTP request, the request could fail for any number of reasons, and this is normal - it is important to wrap the request in a try/catch block to ensure that any issues are handled properly. Failure to do so will typically result in a generic "Something went wrong" error being shown to the end user which both is unhelpful (what went wrong?) and often inappropriate (do we need to show an error to the end user?).

try
{
    // Do something here
    throw new \UnexpectedValueException;
}
catch( \UnexpectedValueException $e )
{
    // Do something else instead
}

It is important to catch the individual exceptions when possible and either show relevant error messages, log the information as needed, or perform another action if possible (in some cases, exceptions may be expected and can even be ignored). You should avoid catching the generic \Exception class unless absolutely necessary - it is better to catch 3 separate more specific Exception subclasses instead.

When you need to show an error to the end user, there is an error() method in \IPS\Output to facilitate this need.

    /**
     * Display Error Screen
     *
     * @param    string                $message             language key for error message
     * @param    mixed                $code                 Error code
     * @param    int                    $httpStatusCode     HTTP Status Code
     * @param    string                $adminMessage         language key for error message to show to admins
     * @param    array                 $httpHeaders         Additional HTTP Headers
     * @param    string                 $extra                 Additional information (such backtrace or API error) which will be shown to admins
     * @param    int|string|NULL        $faultyAppOrHookId    The 3rd party application or the hook id, which caused this error, NULL if it was a core application
     */
    public function error( $message, $code, $httpStatusCode=500, $adminMessage=NULL, $httpHeaders=array(), $extra=NULL, $faultyAppOrHookId=NULL )

The first parameter should be the language string key of the error message to be shown. A full error message to display is also acceptable, in the event the message is coming from a third party or you need to replace variables within the language string. The second parameter should be a unique error code that you generate (using your application key in the code is helpful to ensure it remains unique). The third parameter is the HTTP status code to return to the end user. Error messages should always have a 4xx or 5xx HTTP status code, and you should always use the most appropriate status code possible.  For instance, if the user requested a page that is invalid, you would likely return a 404 status code, while a request for a page that the user does not have permission to view should likely return a 403 status code.

The $adminMessage parameter allows you to show a different message to administrators vs regular end users. This is useful to guide administrators into resolving issues themselves. For example, if the reason an error is being thrown is because the feature is disabled, you may tell the end user "You do not have permission to access this page", but you may want to instead tell the administrator "This page cannot be shown because the setting XYZ is disabled in the Administrator Control Panel".

The $httpHeaders array allows you to send custom headers with the HTTP response, if needed.  For example, if the reason a user reached an error page is because they are rate limited, you may want to send a Retry-After header to indicate to the user agent when they can try again. The $extra parameter allows you to include additional information (such as a backtrace) which will be shown to administrators, and the $faultyAppOrHookId is typically omitted when you are manually calling the error() method.

Be aware that you should call the error() method even if the current request is an AJAX request. The method will automatically handle this situation and return the error information through a JSON response which will be handled automatically (in most cases at least) by the core AJAX javascript libraries.

 

Often times, when an unexpected error occurs you should also log some additional data to the system logs to help diagnose the problem later. Please review our logging documentation for more information about logging data to the system logs.

 

 

Error Codes
 

The first number (the severity) is all that matters. Beyond that, you're free to use whatever you want, though I would recommend using something which is vaguely in line with what we do for consistency.

Out format is: ABC/D

A is a number 1-5 indicating the severity:

Severity Description Examples
1 User does something that is not allowed. Can happen in normal use. User did not fill in a required form element.
2 Action cannot be performed. Will not happen in normal clicking around, but may happen if a URL is shared. User does not have permission to access requested page; Page doesn't exist.
3 Action cannot be performed. Will not happen in normal use. Secure key doesn't match; User submitted a value for a select box that wasn't in the select box.
4 Configuration error that may happen if the admin hasn't set things up properly. Uploads directory isn't writable; Facebook application data was rejected.
5 Any error that should never happen. No login modules exist; Module doesn't have a defined default section.
B is a single character indicating the application (or "S" for code outside any application):
			array(
				'core'		=> 'C',
				'forums'	=> 'F',
				'blog'		=> 'B',
				'gallery'	=> 'G',
				'downloads'	=> 'D',
				'cms'		=> 'T',
				'nexus'		=> 'X',
				'chat'		=> 'H',
				'calendar'	=> 'L'
			)

C is a 3-digit number indicating the class in which the error occurred. We just started at 100 for each application and every time we need a new one, add a number on. It's just to make it unique - we don't reverse-lookup the number anywhere.

D is then an identifier error within the class. The first error code in the class is given 1, if we need more than 9, the next one gets "A" then "B", etc.

 

 

 

So, as a random example, the code "2X196/1" is a level-2 severity error in Commerce. It has the code "196/1" - "196" is \IPS\nexus\modules\front\checkout\checkout and "1" means it was the first error which was added.

 

Some tips:

  • Please don't just copy them blindly from existing code.
  • Use descriptive error messages and make use of the ability to show a different error message to admins where appropriate. If it's a severity 4 error, you probably want to show an admin message.
  • The HTTP status code you use is important so make sure you set that properly. Don't use HTTP 500 for an error code with severity 1 or 2 or a HTTP 4xx error for a code with severity 4 or 5. HTTP 404 and 403 will usually be severity 2, HTTP 429 and 503 will usually be severity 1.

  Report Document


×
×
  • Create New...