local function divide(a, b)
if b == 0 then error("division by zero") end -- adds position info: "file.lua:2: division by zero"
return a / b
end
error("message", 2) -- level 2: blame the caller
error("no position", 0) -- level 0: no position info
error({code = 404, msg = "not found"}) -- any value can be an error object
assert(tonumber("42"), "not a number") -- returns its arguments if truthy, else raises
local f = assert(io.open("file.txt", "r")) -- idiom: functions returning nil, err work with assert
22.2 Catching Errors: pcall and xpcall
local ok, result = pcall(divide, 10, 0)
if not ok then print("Error: " .. result) end --> Error: file.lua:2: division by zero
local ok2, err = pcall(function()
local t = nil
return t.field -- runtime error
end)
print(ok2, err) --> false ...attempt to index a nil value (local 't')
-- xpcall with a message handler (runs before the stack unwinds: good for tracebacks)
local ok3, trace = xpcall(function() error("deep failure") end, debug.traceback)
print(trace)
-- xpcall with arguments (5.2+)
local ok4, value = xpcall(divide, debug.traceback, 10, 2)
-- Error objects
local ok5, e = pcall(error, {code = 500, msg = "server"})
if not ok5 and type(e) == "table" then print(e.code, e.msg) end
22.3 Conventions: nil, err Returns vs Errors
-- Expected failures: return nil plus an error message (like io.open)
local function read_config(path)
local f, err = io.open(path, "r")
if not f then return nil, "cannot open config: " .. err end
local content = f:read("a")
f:close()
return content
end
local content, err = read_config("missing.conf")
if not content then print(err) end
-- Programming errors and violated preconditions: raise with error()
22.4 Structured Error Classes and try/catch Helpers
local AppError = {}
AppError.__index = AppError
AppError.__tostring = function(e) return string.format("[%s] %s", e.kind, e.message) end
function AppError.new(kind, message) return setmetatable({kind = kind, message = message}, AppError) end
local function try(f, catch, finally)
local ok, err = pcall(f)
if not ok and catch then catch(err) end
if finally then finally() end
end
try(function() error(AppError.new("NotFound", "user 42 missing")) end,
function(e) print("caught: " .. tostring(e)) end,
function() print("cleanup") end)
22.5 Warnings (5.4)
warn("@on") -- enable warnings (the lua standalone interpreter starts with them off)
warn("something odd ", "happened")
-- lua -W script.lua enables warnings from the command line