Errors
The global errors table creates and inspects structured errors with categories, details, and retry metadata. It is available without require.
This is an API reference. Each code block is an isolated snippet, not a complete entry. Variables such as err refer to an error returned or created by surrounding application code; the wrapping example assumes db is an application-provided database client.
Creating Errors
-- Simple message (kind defaults to UNKNOWN)
local err = errors.new("something went wrong")
-- With kind, retryable, and details
local err = errors.new({
message = "user not found",
kind = errors.NOT_FOUND,
retryable = false,
details = {user_id = 123}
})
errors.new accepts either a string message or a table with at least a message field. The (kind, message) form is not supported.
Wrapping Errors
Wrap an error to add context while preserving its kind, retry metadata, and details:
local data, err = db:query("SELECT * FROM users")
if err then
return nil, errors.wrap(err, "failed to load users")
end
Error Methods
| Method | Returns | Description |
|---|---|---|
err:kind() |
string | Error category |
err:message() |
string | Error message |
err:retryable() |
boolean/nil | Whether operation can be retried |
err:details() |
table/nil | Structured metadata |
err:stack() |
string | Lua stack trace |
tostring(err) |
string | Full representation |
Checking Kind
if errors.is(err, errors.INVALID) then
-- handle invalid input
end
-- Or compare directly
if err:kind() == errors.NOT_FOUND then
-- handle missing resource
end
Error Kinds
| Constant | Use Case |
|---|---|
errors.NOT_FOUND |
Resource doesn't exist |
errors.ALREADY_EXISTS |
Resource already exists |
errors.INVALID |
Bad input or arguments |
errors.PERMISSION_DENIED |
Access denied |
errors.UNAVAILABLE |
Service temporarily down |
errors.INTERNAL |
Internal error |
errors.CANCELED |
Operation was canceled |
errors.CONFLICT |
Resource state conflict |
errors.TIMEOUT |
Operation timed out |
errors.RATE_LIMITED |
Too many requests |
errors.UNKNOWN |
Unspecified error |
Call Stack
Use errors.call_stack to inspect a structured call stack:
local stack = errors.call_stack(err)
if stack then
print("Thread:", stack.thread)
for _, frame in ipairs(stack.frames) do
print(frame.source .. ":" .. frame.line, frame.name)
end
end
Retryable Errors
Retryability is error metadata, not a property guaranteed by an error kind. Check the value returned by err:retryable() rather than inferring it from err:kind(). A result of nil means the error does not specify whether retrying is appropriate.
if err:retryable() then
-- safe to retry
end
Error Details
local err = errors.new({
message = "validation failed",
kind = errors.INVALID,
details = {
errors = {
{field = "email", message = "invalid format"},
{field = "age", message = "must be positive"}
}
}
})
local details = err:details()
for _, e in ipairs(details.errors) do
print(e.field, e.message)
end