Lua Error Handling
Error handling during program execution is essential. Unexpected errors can occur during file operations, data transfers, and web service calls. Neglecting error information can lead to information leakage and program failure.
In any programming language, error handling is necessary. Error types include:
- Syntax errors
- Runtime errors
Syntax Errors
Syntax errors are usually caused by improper use of program components (such as operators and expressions). A simple example is as follows:
-- test.lua file
a == 2
The execution result of the above code is:
lua: test.lua:2: syntax error near '=='
As you can see, a syntax error has occurred. There is a difference between one "=" and two "=". One "=" is an assignment expression, while two "=" is a comparison operation.
Another example:
Example
for a= 1,10
print(a)
end
Executing the above program will result in the following error:
lua: test2.lua:2: 'do' expected near 'print'
Syntax errors are simpler than runtime errors. Runtime errors cannot pinpoint the specific error, but syntax errors can be quickly resolved. For the above example, we just need to add "do" under the for statement:
Example
for a= 1,10
do
print(a)
end
Runtime Errors
Runtime errors occur when the program executes normally but outputs error messages. The following example results in an error due to incorrect input parameters:
function add(a,b)
return a+b
end
add(10)
When we compile and run the following code, the compilation is successful, but an error occurs during runtime:
lua: test2.lua:2: attempt to perform arithmetic on local 'b' (a nil value)
stack traceback:
test2.lua:2: in function 'add'
test2.lua:5: in main chunk
[C]: ?
In Lua, calling a function with inconsistent actual and formal parameters can still succeed. Extra parameters are discarded, and missing parameters are filled with nil.
The error message above is due to parameter b being filled with nil and participating in the addition operation.
If the add function does not contain "return a+b" but "print(a,b)", the result would be "10 nil" without an error.
Error Handling
We can use two functions: assert and error to handle errors. An example is as follows:
Example
local function add(a,b)
assert(type(a) == "number", "a is not a number")
assert(type(b) == "number", "b is not a number")
return a+b
end
add(10)
Executing the above program will result in the following error:
lua: test.lua:3: b is not a number
stack traceback:
[C]: in function 'assert'
test.lua:3: in local 'add'
test.lua:6: in main chunk
[C]: in ?
In the example, assert first checks the first parameter. If there is no issue, assert does nothing; otherwise, it throws the second parameter as an error message.
Error Function
Syntax format:
error (message [, level])
Function: Terminates the currently executing function and returns the content of message as the error message (the error function never returns).
Usually, error appends some information about the error location to the message header.
The Level parameter indicates the position where the error is obtained:
- Level=1 [default]: the location where error is called (file + line number)
- Level=2: the function that calls the function that calls error
- Level=0: does not add error location information
pcall and xpcall, debug
In Lua, error handling can be done using the pcall (protected call) function to wrap the code that needs to be executed.
pcall receives a function and parameters to be passed to it, executes it, and returns whether there was an error or not; true or false, and errorinfo.
The syntax format is as follows:
if pcall(function_name, ...) then
-- No error
else
-- Some error
end
Simple example:
Example
> =pcall(function(i) print(i) end, 33)
33
true
> =pcall(function(i) print(i) error('error..') end, 33)
33
false stdin:1: error..
> function f() return false,2 end
> if f() then print '1' else print '0' end
0
pcall calls the first parameter in a "protected mode," so pcall can catch any errors during function execution.
Usually, when an error occurs, more debugging information is desired than just the location of the error. However, when pcall returns, it has already destroyed part of the call stack.
Lua provides the xpcall function, which accepts a second parameter—an error handling function. When an error occurs, Lua calls the error handling function before unwinding the call stack, allowing the use of the debug library to obtain additional information about the error.
- debug.debug: provides a Lua prompt for the user to check the cause of the error
- debug.traceback: constructs an extended error message based on the call stack
>=xpcall(function(i) print(i) error('error..') end, function() print(debug.traceback()) end, 33) 33 stack traceback: stdin:1: in function <stdin:1> [C]: in function 'error' stdin:1: in function <stdin:1> [C]: in function 'xpcall' stdin:1: in main chunk [C]: in ? false nil
xpcall example 2:
Example
function myfunction ()
n = n/nil
end
function myerrorhandler( err )
print( "ERROR:", err )
end
status = xpcall( myfunction, myerrorhandler )
print( status)
Executing the above program will result in the following error:
ERROR: test2.lua:2: attempt to perform arithmetic on global 'n' (a nil value)
false