Version: v0.8.0 - Beta.  We welcome contributors & feedback.

Error Handling

How to Think About Errors

You might think that errors are bad and should be avoided at all costs. But this isn’t necessarily true.

For web apps, when something goes wrong, it’s usually best to let your program die immediately instead of trying to recover from it.

  1. An “injured” script can do a lot more damage than a dead one, and could even lead to a security vulnerability.
  2. Dying immediately means that the error will be triggered closer to the source of the problem, making it easier to find and fix.
  3. It avoids putting your program in ambiguous “half-error” states that are more complicated and difficult to maintain.
  4. Each web request is self-contained and has a very short lifecycle, so recovery is less important than in other kinds of (non-web) systems.

Triggering Errors 

You can trigger an error manually with the die function.

if !file'important.txt'.exists() {

    die('Important file not found.')
    ^^^
}

Result Objects 

If a function fails in a way that you are 100% sure should not end the program, we recommend returning a Result object.

This forces the caller to handle any potential errors in a safe way.

fun runProcess {

    // ... do some work that could fail ...

    if $isMissingData {
        // Fail result with a failCode
        return Result.fail('missingData')
    }
    else {
        // Success result with data
        return Result.ok($data)
    }
}


// Using a returned Result object:

$result = runProcess()

if $result.isOk() {
    $data = $result.get()
}

Try/Catch 

There are times when you have a good reason to treat a normally fatal error as non-fatal.

In these cases, you can use try/catch to trap the error.

The catch block will only run if there is an error in the try block.

The $error argument will contain the error message or information.

$content = ''
try {
    // Triggers an error if it can't read the file.
    $content = File.read('important.txt')
}
catch $error {
    // Try to restore it and continue.
    $content = getDefaultContent()
    File.write('important.txt', $content)
}

finally

A finally block can be used to define code that will run regardless of whether or not an error occurred.

This is optional, and is usually intended for cleanup logic that needs to be run before the program ends.

try {
    // Initial code
}
catch $error {
    print($error.message())
}
finally {
    // Always run this after the above blocks complete
}

Error Logging 

Errors that aren’t triggered in development mode are always logged to data/logs/errors.txt.