Lua/Errors
Lua modules based on the Scribunto/Lua extension are stored in resource pages using the Module: namespace. Each module uses a table to hold functions and variables, and that containing table is returned at the end of the module code.[1] This lesson will show you how to troubleshoot script errors and handle run-time errors in your scripts.
Prerequisites
This lesson assumes you have already completed the Tables lesson.
Create a Lua Script with Errors and Error Handling
To create a Lua script with errors and error handling:
- Navigate to Module:Sandbox.
- Clear all existing code.
- It's a sandbox. Everyone is free to play in the sandbox. But if you find another user is actively editing the sandbox at the same time, you may also use Module:Sandbox/Username, where Username is your Wikiversity username.
- Add the following code and save the page:
local p = {} local function reciprocal1(value) return 1 / value end function p.test1(frame) local value = frame.args[1] return reciprocal1(value) end local function reciprocal2(value) if value == nil then error('value must exist') end if tonumber(value) == nil then error('value must be a number') end if tonumber(value) == 0 then error('value must not be 0') end return 1 / value end function p.test2(frame) local value = frame.args[1] return reciprocal2(value) end local function reciprocal3(value) assert(value, 'value must exist') assert(tonumber(value), 'value must be a number') assert(tonumber(value) ~= 0, 'value must not be zero') return 1 / value end function p.test3(frame) local value = frame.args[1] return reciprocal3(value) end function p.test4(frame) local value = frame.args[1] if pcall(function () result = reciprocal3(value) end) then return result else return 'Error: Value must exist, must be numeric, and not zero.' end end return p
Test Your Lua Script
To test your Lua script:
- Navigate to either the Module_talk:Sandbox page, the Wikiversity:Sandbox page, or your own user or sandbox page.
- Add the following code and save the page:
;Reciprocal 1
:{{#invoke:Sandbox|test1}}
:{{#invoke:Sandbox|test1|x}}
:{{#invoke:Sandbox|test1|0}}
:{{#invoke:Sandbox|test1|2}}
;Reciprocal 2
:{{#invoke:Sandbox|test2}}
:{{#invoke:Sandbox|test2|x}}
:{{#invoke:Sandbox|test2|0}}
:{{#invoke:Sandbox|test2|2}}
;Reciprocal 3
:{{#invoke:Sandbox|test3}}
:{{#invoke:Sandbox|test3|x}}
:{{#invoke:Sandbox|test3|0}}
:{{#invoke:Sandbox|test3|2}}
;Reciprocal 4
:{{#invoke:Sandbox|test4}}
:{{#invoke:Sandbox|test4|x}}
:{{#invoke:Sandbox|test4|0}}
:{{#invoke:Sandbox|test4|2}}
The result should be similar to:
- Reciprocal 1
- Script error
- Script error
- inf
- 0.5
- Reciprocal 2
- Script error
- Script error
- Script error
- 0.5
- Reciprocal 3
- Script error
- Script error
- Script error
- 0.5
- Reciprocal 4
- Error: Value must exist, must be numeric, and not zero.
- Error: Value must exist, must be numeric, and not zero.
- Error: Value must exist, must be numeric, and not zero.
- 0.5
Understand Your Lua Script
To understand your Lua script reciprocal1 function:
local function reciprocal1(value)declares a local function namedreciprocal1that accepts a single parametervalue, which is the value whose reciprocal will be returned.return 1 / valuereturns the reciprocal of value.endends the function.
To understand your Lua script test1 function:
function p.test1(frame)declares a function namedtest1that accepts a single parameterframe, which is the object used to access parameters passed from #invoke.local value = frame.args[1]defines a local variable namedvalueand assigns the value of the first frame argument (parameter) passed with #invoke.return reciprocal1(value)calls thereciprocal1function, passing the variablevalueand returns the result.endends the function.
To understand your Lua script reciprocal2 function:
local function reciprocal2(value)declares a local function namedreciprocal2that accepts a single parametervalue, which is the value whose reciprocal will be returned.if value == nil thencreates a conditional code block and tests to see ifvalueisnil. If it is, an error is generated.error('value must exist')generates an error with the given literal string as the error statement. Usingerror()allows the script writer to determine the text of the error message that is returned to the calling function or wiki page that invoked the function.- When an error is generated, execution immediately returns to the calling function. Any additional code in the same function that comes after the error is not processed.
if tonumber(value) == nilcreates a conditional code block and tests to see ifvalueis numeric. If it is not,tonumberreturnsniland an error is generated.if tonumber(value) == 0creates a conditional code block and tests to see ifvalueis0. If it is, an error is generated.return 1 / valuereturns the reciprocal of value.endends the function.
To understand your Lua script test2 function:
function p.test2(frame)and the following code declares a function namedtest2that accepts a single parameterframe, which is the object used to access parameters passed from #invoke.local value = frame.args[1]defines a local variable namedvalueand assigns the value of the first frame argument (parameter) passed with #invoke.return reciprocal2(value)calls thereciprocal2function, passing the variablevalueand returns the result.endends the function.
To understand your Lua script reciprocal3 function:
local function reciprocal3(value)declares a local function namedreciprocal3that accepts a single parametervalue, which is the value whose reciprocal will be returned.assert(value, 'value must exist')creates a self-contained conditional code block and tests to see ifvalueisnilIf it is, an error is generated.- It is best practice to use
assertto document and test any assumptions that are made regarding passed parameters.
- It is best practice to use
assert(tonumber(value), 'value must be a number')creates a self-contained conditional code block and tests to see ifvalueis numeric. If it is not,tonumberreturnsniland an error is generated.assert(tonumber(value) ~= 0, 'value must not be zero')creates a conditional code block and tests to see ifvalueis0. If it is, an error is generated.return 1 / valuereturns the reciprocal of value.endends the function.
To understand your Lua script test3 function:
function p.test3(frame)and the following code declares a function namedtest3that accepts a single parameterframe, which is the object used to access parameters passed from #invoke.local value = frame.args[1]defines a local variable namedvalueand assigns the value of the first frame argument (parameter) passed with #invoke.return reciprocal3(value)calls thereciprocal3function, passing the variablevalueand returns the result.endends the function.
To understand your Lua script test4 function:
function p.test4(frame)and the following code declares a function namedtest4that accepts a single parameterframe, which is the object used to access parameters passed from #invoke.local value = frame.args[1]defines a local variable namedvalueand assigns the value of the first frame argument (parameter) passed with #invoke.if pcall(function () result = reciprocal3(value) end) thencreates a conditional code block that calls thereciprocal3function, passingvalueand storing the result. If no error occurs,resultis returned. If an error occurs, a literal string is returned instead.pcall()uses the pcall (protected call) function to call a function and catch any errors that occur.function () ... endcreates a self-contained anonymous function that executes the code in ... as a function call.- The anonymous function is necessary to save the result of the
reciprocal3function while also usingpcall()to catch any errors that occur.
- The anonymous function is necessary to save the result of the
endends the function.
Conclusion
Congratulations! You've now created, tested, and understood a Lua script with error handling. Continue on to the Math Library lesson or return to the main Lua page to learn about other Lua code libraries.