This first edition was written for Lua 5.0. While still largely relevant for later versions, there are some differences.
The fourth edition targets Lua 5.3 and is available at Amazon and other bookstores.
By buying the book, you also help to support the Lua project.


8.5 – Error Messages and Tracebacks

Although you can use a value of any type as an error message, usually error messages are strings describing what went wrong. When there is an internal error (such as an attempt to index a non-table value), Lua generates the error message; otherwise, the error message is the value passed to the error function. In any case, Lua tries to add some information about the location where the error happened:

    local status, err = pcall(function () a = 'a'+1 end)
    print(err)
     --> stdin:1: attempt to perform arithmetic on a string value
    
    local status, err = pcall(function () error("my error") end)
    print(err)
     --> stdin:1: my error
The location information gives the file name (stdin, in the example) plus the line number (1, in the example).

The error function has an additional second parameter, which gives the level where it should report the error; with it, you can blame someone else for the error. For instance, suppose you write a function and its first task is to check whether it was called correctly:

    function foo (str)
      if type(str) ~= "string" then
        error("string expected")
      end
      ...
    end
Then, someone calls your function with a wrong argument:
    foo({x=1})
Lua points its finger to your function---after all, it was foo that called error---and not to the real culprit, the caller. To correct that, you inform error that the error you are reporting occurred on level 2 in the calling hierarchy (level 1 is your own function):
    function foo (str)
      if type(str) ~= "string" then
        error("string expected", 2)
      end
      ...
    end

Frequently, when an error happens, we want more debug information than only the location where the error occurred. At least, we want a traceback, showing the complete stack of calls leading to the error. When pcall returns its error message, it destroys part of the stack (the part that went from it to the error point). Consequently, if we want a traceback, we must build it before pcall returns. To do that, Lua provides the xpcall function. Besides the function to be called, it receives a second argument, an error handler function. In case of errors, Lua calls that error handler before the stack unwinds, so that it can use the debug library to gather any extra information it wants about the error. Two common error handlers are debug.debug, which gives you a Lua prompt so that you can inspect by yourself what was going on when the error happened (later we will see more about that, when we discuss the debug library); and debug.traceback, which builds an extended error message with a traceback. The latter is the function that the stand-alone interpreter uses to build its error messages. You also can call debug.traceback at any moment to get a traceback of the current execution:

    print(debug.traceback())