Error Handling

Responding to errors gracefully is a hallmark of good programming. Errors in Lasso run the gamut from expected errors, such as a database search that returns no records, to syntax errors that require fixing before a page will even process. Lasso provides tools to manage errors at several different levels, which can act redundantly to ensure that no errors will be missed.

Error Types

The following lists the types of errors that can occur in Lasso:

Web Server Errors
These include “file not found” errors and access violations in realms. These will be reported with standard HTTP response codes (e.g. 404 for “File Not Found”).
Syntax Errors
These include misspellings of type or method names, missing delimiters, and mismatched types. Lasso will return an error message rather than the processed Lasso page if it encounters a syntax error.
Action Errors
These include missing or misspelled database names, table names, or field names, and other problems specifying database actions. The database action cannot be performed until the error is corrected.
Database Errors
These are generated by the data source application and include type mismatches, missing required field values, and others. Lasso will report the returned error from the data source application without modification.
Logical Errors
These are problems that cause a page to process unexpectedly even though the syntax of the code is correct. These include infinite loops, missing cases, and assumptions about the size or composition of a found set.
Security Violations
These are not strictly errors, but are attempts to perform database actions or file accesses that are not allowed by the permissions set for the current user.
Operating System Errors
These are errors reported by the operating system Lasso is running on. One example of these errors is trying to perform file operations on a directory.

Some errors are more serious than others. Pages will not be processed at all if they contain syntax errors or if there are operational problems that prevent Lasso Server from being accessed. Other errors are commonly encountered in the normal use of a website. Most database errors and security violations are handled by simply showing a “No Records Found” message or displaying a security dialog box to prompt the user for a username and password.

The following mechanisms for handling errors can be used individually or in concert to provide comprehensive error handling:

  • Automatic error reporting is performed by Lasso in response to unhandled errors.
  • A custom error page allows the automatic error report to be replaced by a custom page. Custom error pages are usually created for each site on a server.
  • Error handling methods allow action and logical errors and security violations to be handled within a Lasso page.
  • Error handling methods allow advanced error handling to be built into Lasso pages. These techniques allow error handling routines to be built into a page without disrupting the normal processing of a page if no errors occur.

Error Reporting

Lasso Server delivers an error report in response to an error that prevents processing of the page. This error report contains an error code, message, and stack trace which can be used to identify the cause and location of an error. The various parts of the stack can be accessed using the error_… methods.

While the standard error report is great for developers, it is meaningless for visitors to your website. A custom error page can be defined to be displayed to a site visitor rather than Lasso’s built-in error report. The error message displayed on a custom error page will depend on the Lasso code used on the custom page.

To define a custom error page, create a file named error.lasso and place it in the root of the web serving folder. Each distinct web serving folder on a host can have a custom error page.

Custom error pages can be further fine-tuned by placing the error.lasso file in the web serving folder’s subdirectories. Lasso Server will process the first error.lasso it encounters on the file path, starting with the current directory and continuing upward until it reaches the root of the web serving folder. If none are found, Lasso Server will use the default error report.

Error Reporting Methods

The error_… methods in Lasso allow custom errors to be reported and provide access to the most recently reported error by the code executing in the current Lasso page. This allows a developer to check for specific errors and respond, if necessary, with an error message or with code to correct the error.

Lasso maintains a single error code and error message, which is set by any method that reports an error. The error code and error message should be checked immediately after a method that may report an error. If any intervening methods or expressions report errors, then the original error code and error message will be lost.

Custom errors can be created using the error_setErrorMessage and error_setErrorCode methods. Once set, the error_currentError method or error_code and error_msg methods will return the custom error code and message. A developer can use these methods to incorporate both built-in and custom error codes into the error recovery mechanisms for a site.

error_currentError(-errorCode=?)

Returns the current error message. The optional -errorCode parameter causes the current error code to be returned instead.

error_code()

Returns the current error code.

error_msg()

Returns the current error message.

error_obj()

Returns the current error name from the Lasso variable $_err_obj, or “null” if no error object is present.

error_push()

Pushes the current error condition onto a stack and resets the current error code and error message.

error_pop()

Restores the most recent error condition stored using error_push.

error_reset()

Resets the current error code and error message.

error_setErrorCode(code)

Sets the current error code to a custom value.

error_setErrorMessage(msg)

Sets the current error message to a custom value.

error_stack()

Returns the stack trace for the current error.

Display the Current Error

The following code will display a short error message using the error_msg method and the error_code method. If the code on the page is executing normally and there is no current error to report then the code will return the result shown below:

'The current error is ' + error_code + ': ' + error_msg
// => The current error is 0: No Error

Alternatively, the error_currentError method could be used to create the same message with the following code:

'The current error is ' + error_currentError(-errorCode) + ': ' + error_currentError
// => The current error is 0: No Error

Set the Current Error

The current error code and message can be set using the error_setErrorCode and error_setErrorMessage methods. These methods will not affect the execution of the current Lasso page, but will simply set the current error so it will be returned by the error_currentError method or error_code and error_msg methods.

In the following example, the error message is set to “A custom error occurred” and the error code is set to “-1”:

error_setErrorMessage('A custom error occurred')
error_setErrorCode(-1)

The error_currentError method now reports this custom error when it is called later in the page, unless any intervening code changed the error message again:

'The current error is ' + error_code + ': ' + error_msg
// => The current error is -1: A custom error occurred

The current error code and message can also be set using the error_code and error_msg methods:

error_msg = 'A custom error occurred'
error_code = -1

Store and Restore the Current Error

The following code uses the error_push and error_pop methods to store the current error code and message before the protect block is executed. This allows the protect block to execute without any previous error on the page bleeding into it and mistakenly triggering the handle_failure block. Then the error code and message are restored at the end of the block.

error_push  // Push error onto stack

protect => { // Protect from failure
   handle_failure => {
      // Handle any errors generated within the protect block
   }
   // ...
}

error_pop  // Retrieve error from stack

The error_push and error_pop methods can also be used to prevent custom methods from modifying the current error condition, while still using error-handling code within the method. The following code stores the current error code and message at the beginning of the custom method definition. The error code and message are restored just before the custom method returns a value.

define myMethod() => {
   // Push current error onto stack
   error_push

   // ... code that may generate an error ...

   // Retrieve error from stack
   error_pop

   return 'myValue'
}

Reset the Current Error

The following code demonstrates how to use the error_reset method to reset the error message to “No error” and the error code to “0”:

error_code = -1
error_msg  = 'Too slow'
error_code + ': ' + error_msg

// => -1: Too slow

error_reset
error_code + ': ' + error_msg

// => 0: No error

Lasso Errors

The table below lists Lasso’s standard error codes and values.

Lasso Error Codes and Messages
Error Method Value
error_code_noerror 0
error_msg_noerror No error
error_code_fileNotFound 404
error_msg_fileNotFound File not found
error_code_runtimeAssertion -9945
error_msg_runtimeAssertion Runtime assertion
error_code_aborted -9946
error_msg_aborted General Abort
error_code_methodNotFound -9948
error_msg_methodNotFound Method not found
error_code_divideByZero -9950
error_msg_divideByZero Divide by Zero
error_code_invalidParameter -9956
error_msg_invalidParameter Invalid parameter
error_code_networkError -9965
error_msg_networkError Network error
error_code_resNotFound -9967
error_msg_resNotFound Resource not found

Error Handling

Lasso includes powerful error handling methods that allow areas of a page to be protected and errors to be handled. Error-specific handlers are called if any errors occur in a protected area of a page. These methods allow comprehensive error handling to be built into a page without disturbing the code of the page with many conditionals and special cases.

Error Handling Methods

fail(msg::string)
fail(code::integer, msg::string, stack::string=?)

Halts execution and generates the specified error. Can be called with just an error message, an error code and an error message, or an error code, message, and stack trace.

fail_if(cond, msg::string)
fail_if(cond, code::integer, msg::string)

Conditionally halts execution and generates the specified error if the specified condition evaluates to “true”. Takes two or three parameters: a conditional expression, an integer error code, and a string error message or just the conditional expression and the error message.

handle(cond=?)

Conditionally executes a given capture block after the code in the current capture block or Lasso page has completed or a fail method is called. May take a conditional expression as a parameter that limits executing the capture block to when the conditional statement evaluates to “true”. If an error occurs in the Lasso code before the handle block is defined, then the handle’s capture block will not be executed.

handle_failure(cond=?)

Functions the same as handle except that the contents are executed only if an error was reported in the surrounding capture block or Lasso page.

protect()

Protects a portion of a page. If code inside the given capture block throws an error or a fail method is executed inside the capture block, then the error is not allowed to propagate outside the protected capture block. This means that a fail will only halt the execution of the rest of the code in the protect capture, and execution will resume starting with the code following that capture.

abort()

Sets the current error code to error_code_aborted and stops Lasso from continuing execution. This cannot be stopped with protect.

handle and handle_failure

The handle method is used to specify a block of code that will be executed after the current code segment is completed. The handle method can take a single parameter that is a conditional expression (defaults to “true”). If the conditional expression evaluates as “true”, then the code in the given capture block is executed.

All handle and handle_failure methods are processed sequentially, giving each a chance to be executed in the order they were specified and allowing for execution of multiple handle blocks. Therefore, it is necessary to define them before logic that could halt execution. Any handle methods that are defined after a script failure will not be executed. It is generally good practice to place handle and handle_failure methods at the start of the parent capture block, most commonly a protect capture block. (This is a change from previous versions of Lasso and increases the reliability of executing fault-condition fallbacks.)

The handle methods will not be executed if a syntax error occurs while Lasso is parsing a page. When Lasso encounters a syntax error it returns an error page instead of processing the code on the page.

The handle methods will be executed if a logical error occurs while Lasso is processing a page. However, the returned result will be an error message rather than the output of the page. Code within the handle capture block can redirect the user to another page using redirect_url or can replace the contents of the page being served.

There are two ways to use handle methods within a Lasso page:

  1. When used on their own in a Lasso page, the code inside the handle methods will be conditionally executed after all the rest of the code in the Lasso page has completed. The handle methods can be used to provide post-processing code for a Lasso page.
  2. When used within any Lasso capture block, the code inside the handle methods will be conditionally executed after the capture block is executed. The handle methods will most commonly be used within a protect block to provide error handling.

fail and fail_if

The fail method allows an error to be triggered from within Lasso code. Use of the fail method immediately halts execution of the current page and starts execution of any registered handle method contained within.

The fail method can be used in the following ways:

  • To report an unrecoverable error. Just as Lasso automatically halts execution of a Lasso page when a syntax error or internal error is encountered, Lasso code can use the fail method to report an error that cannot be recovered from:

    fail(-1, 'An unrecoverable error occurred')
    
  • To trigger immediate execution of the page’s handle methods. If an error is handled by one of the handle methods specified in the Lasso page (outside of any other capture blocks), then the code within the handle capture block will be executed. The handle block can recover from the error and allow execution to continue by using the error_reset method.

  • To trigger immediate execution of a protect capture block’s handle block, which is described in the next section.

The fail_if method allows conditional execution of a fail without using a full if/else conditional. The first parameter to fail_if is a conditional expression. The last two parameters are the same integer error code and string error message as in the fail method. In the following example the fail_if method is only executed if the variable “x” does not equal “0”:

fail_if(#x != 0, 100, "Value does not equal 0.")

protect

The protect method is used to catch any errors that occur within the code surrounded by the capture block. They create a protected environment from which errors cannot propagate to the page itself. Even if Lasso reports an internal error it will be caught by the protect method, allowing the rest of the page to execute successfully.

Any fail or fail_if methods called within protect capture blocks will halt execution only of the code contained within the protect capture block. Any handle capture blocks contained within the protect capture blocks will be conditionally executed. However, Lasso requires these handle capture blocks to be present before the error occurs, so put them at the top of the protect capture block. The Lasso page will continue executing normally after the closing of the protect capture block.

The protect capture blocks can be used for the following purposes:

  • To protect a portion of a page so that any errors that would normally result in an error message being displayed to the user are instead handled in the internal handle capture blocks.
  • To provide advanced flow control in a page. Code within the protect capture blocks is executed normally until a fail signal is encountered. The code then jumps immediately to the internal handle block.

Protect a Portion of a Page from Errors

Wrap the portion of the page that needs to be protected in a protect capture block. Any internal errors that Lasso reports will be caught by the protect capture block and not reported to the end user. A handle capture block should be included to handle the error if necessary.

In the following Lasso code an attempt is made to set a variable “myVar” to “null”. However, if the variable has not been previously declared, an error would be reported, and the page would not continue processing. Since the code is executed within a protect capture block, no error is reported, and the protect capture block exits silently while the Lasso page resumes execution after the protect block.

protect => {
   $myVar = null
}

Use protect with Custom Errors

The following example shows a protect capture block that surrounds code containing two fail_if statements with custom error codes “-1” and “-2”. A handle block at the start of the protect is set to intercept either of these custom error codes. This handle block will only execute if one of the fail_if methods executes successfully.

protect => {^
   handle => {^
      if(error_code == -1)
         '... Handle custom error -1 ...'
      else(error_code == -2)
         '... Handle custom error -2 ...'
      else
         '... Another error has occurred ...'
      /if
   ^}

   'Before the fail_if\n'

   local(
      condition_one = false,
      condition_two = true
   )
   fail_if(#condition_one, -1, 'Custom error -1')
   fail_if(#condition_two, -2, 'Custom error -2')

   '\nAfter the fail_if'
^}

// =>
// Before the fail_if
// ... Handle custom error -2 ...