# Convenient error handling in tarantool

Because Lua code deserves better error handling. This module helps you understand what code path lead to creation of a particular exception object.

## Example

    errors = require('errors')

    DoSomethingError = errors.new_class("DoSomethingError")

    function do_something()
        local failure_condition = true
        local result = "bar"

        if failure_condition then
            return nil, DoSomethingError:new("failure_condition is true")
        end

        return result
    end

    res, err = do_something()

    if err ~= nil then
        print(err)
    end

This code will print:

    DoSomethingError: failure_condition is true
    stack traceback:
        test.lua:10: in function 'do_something'
        test.lua:16: in main chunk

See that you have an exception type, message and traceback recorded inside the exception object. It can be converted to string using the `tostring()` function.

## Uniform error handling

The module praises uniform error handling and provides `pcall` API, which unifies return values:

    > print( DoSomethingError:pcall(do_something) )
    nil     DoSomethingError: failure_condition is true
    stack traceback:
        test.lua:10: in function 'do_something'
        test.lua:16: in main chunk

    > print( DoSomethingError:pcall(error, 'some functions still raise') )
    nil     DoSomethingError: some functions still raise
    stack traceback:
            [C]: in function 'xpcall'
            /opt/errors/errors.lua:139: in function 'pcall'
            [string "return print( DoSomethingEr"]:1: in main chunk

In both cases pcall returns the same pattern `nil, err`.

If there were no error raised, `pcall` doesn't modify any return values:

    > print( DoSomethingError:pcall(function() return nil, "foo", "bar" end) )
    nil     foo     bar

## Uniform API for net.box stuff

It may be tricky to debug errors, when they arise on a remote host: `net.box` throws an exception and doesn't keep stack trace from the remote.

To simplify debugging in this case use `return nil, err` pattern with conjunction of errors.netbox_eval or netbox_call. It'll collect stacktrace from both local and remote hosts and restore metatables (which can't be transfed over network).

    > conn = require('net.box').connect('localhost:3301')
    > print( errors.netbox_eval(conn, 'return nil, DoSomethingError:new("oops")') )
    nil     DoSomethingError: oops
    stack traceback:
            eval:1: in main chunk
    during net.box eval on localhost:3301
    stack traceback:
            [string "return print( errors.netbox_eval("]:1: in main chunk
            [C]: in function 'pcall'

## Naming conventions

- Error class should be named in `CamelCase`.
- Error class should end with suffix `Error`.
- See examples: `ReadFileError`, `DecodeYamlError`, `CheckSchemaError`.

generated by LDoc 1.4.6 Last updated 2021-08-16 14:59:27