Skip to content

tarantool/errors

Repository files navigation

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.