Lua Error Handling

Error handling during program execution is necessary. Unexpected errors can occur during file operations, data transfer, and web service calls. If error information is not handled properly, it can lead to information leakage, program failure, and other issues.

Any programming language requires error handling. 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 文件
a == 2

The execution result of the above code is:

lua: test.lua:2: syntax error near '=='

As you can see, a syntax error occurred above; one "=" sign is different from two "=" signs. One "=" is an assignment expression, and two "=" is a comparison operation.

Another example:

Example

for a= 1,10
   print(a)
end

Executing the above program will produce the following error:

lua: test2.lua:2: 'do' expected near 'print'

Syntax errors are simpler than program runtime errors. Runtime errors cannot locate the specific error, but syntax errors can be solved quickly. For example, in the above example, we just need to add "do" under the for statement:

Example

for a= 1,10
do
   print(a)
end

Runtime Errors

A runtime error is when the program executes normally but outputs an error message. The following example reports an error during execution due to incorrect parameter input:

function add(a,b)
   return a+b
end

add(10)

When we compile and run the following code, compilation can succeed, but the following error will occur at 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, when calling a function, even if the actual parameter list and the formal parameter list are inconsistent, the call can still succeed. Excess parameters will be discarded, and missing parameters will be filled with nil.

The above error message is because parameter b is filled with nil, and nil participates in the + operation.

Ifaddinside the function is not"return a+b"but rather"print(a,b)"then the result becomes"10 nil"no error will be reported.


Error Handling

We can use two functions: assert and error to handle errors. Example 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 produce the following error:

lua: test.lua:3: b 不是一个数字
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 problem, assert does nothing; otherwise, assert 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)

Normally, error appends some error location information to the head of the message.

The Level parameter indicates where to obtain the error location:

  • Level=1 [default]: the position of the error call (file + line number)
  • Level=2: indicates which function called the function that calls error
  • Level=0: do not add error location information

pcall and xpcall, debug

To handle errors in Lua, you can use the function pcall (protected call) to wrap the code that needs to be executed.

pcall receives a function and the parameters to pass to it, and executes it. Execution results: with error, without error; return value true or false, errorinfo.

The syntax format is as follows

if pcall(function_name, ….) then
-- 没有错误
else
-- 一些错误
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 error during function execution.

Usually, when an error occurs, you want more debugging information, not just the location of the error. But when pcall returns, it has already destroyed part of the call stack content.

Lua provides the xpcall function. xpcall receives a second parameter — an error handling function. When an error occurs, Lua calls the error handling function before the call stack unwinds, so you can use the debug library in this function to obtain extra information about the error.

The debug library provides two general error handling functions:

  • debug.debug: provides a Lua prompt for users to check the cause of the error
  • debug.traceback: builds 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 usage 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 produce the following error:

ERROR:    test2.lua:2: attempt to perform arithmetic on global 'n' (a nil value)
false
Other Extensions