Topic 08-errors.md
Errors
Return Errors with Multiple Values
Because Lua functions may return multiple values, they can return error strings
together with the status code. The classic example is io,open
which usually
returns a file object, but will return both a nil
and an error message if the file
cannot be opened:
> = io.open("hello.txt") nil hello.txt: No such file or directory 2
The convention is that if a function may normally and routinely fail, then it should return the error as well.
However, if you pass invalid values to a function, it will throw an error:
table.insert(true,1) --> error: bad argument #1 to 'insert' (table expected, got boolean)
Likewise, table.concat will raise an error if the table has any element that isn’t a number or a string. It demands your immediate attention because it is much easier to fix the error than go through hundreds of kB of output text to find some nonsense.
> t = {'h',{}} > = table.concat(t) stdin:1: invalid value (table) at index 2 in table for 'concat' stack traceback: [C]: in function 'concat' stdin:1: in main chunk
Catching Errors with pcall
Even in the most careful programs, something will go wrong, and you do not want users to witness a crash with a stack traceback. Also, it is often possible to recover from the situation. Languages with exception handling encourage the ‘throwing’ or ‘raising’ of errors because then the error handling code is kept away from the ‘normal’ logic – what is sometimes called ‘the happy path’.
There is no try/except
statement in Lua, but there is a function pcall
(or ‘protected call’) which will call a Lua function safely. It will return the status
and anything returned by the function. If the status is false
, then the second
return value is the error message.
> = pcall(table.concat,t) false invalid value (table) at index 2 in table for 'concat' > = pcall(table.concat,{'one','two'}) true onetwo
Anonymous functions are useful for blocks that can raise errors:
local status,err = pcall(function() do_something() do_another() and_again() end) if not status then print('error',err) end
You can raise your own errors, using error
. In its simplest form it will indicate
that the error came from the current line:
--> error is reported at this line; program will give a stacktrace if not right then error("was not right!") end
There can also be a second parameter that indicates where the error came from:
function not_right_error() error("was not right",2) -- i.e, _calling_ function raised this end --> error still reported at this line if not right then not_right_error() end
The function assert raises an error if a condition fails; it may be given an optional message.
--> message 'assertion failed...." assert(n > 0) --> message "size must be positive" assert(n > 0,"size must be positive")
An equivalent Lua version looks like this:
function assert(value,message) if not value then if message == nil then message = "assertion failed" end error(message,2) else return value end end