错误处理

带分类和重试元数据的结构化错误处理。全局 errors 表无需 require 即可使用。

创建错误

-- 简单消息(类型默认为 UNKNOWN)
local err = errors.new("something went wrong")

-- 指定类型
local err = errors.new(errors.NOT_FOUND, "user not found")

-- 完整构造函数
local err = errors.new({
    message = "user not found",
    kind = errors.NOT_FOUND,
    retryable = false,
    details = {user_id = 123}
})

包装错误

添加上下文同时保留类型、可重试性和详情:

local data, err = db.query("SELECT * FROM users")
if err then
    return nil, errors.wrap(err, "failed to load users")
end

错误方法

方法 返回 描述
err:kind() string 错误类别
err:message() string 错误消息
err:retryable() boolean/nil 操作是否可重试
err:details() table/nil 结构化元数据
err:stack() string Lua 堆栈跟踪
tostring(err) string 完整表示

检查类型

if errors.is(err, errors.INVALID) then
    -- 处理无效输入
end

-- 或直接比较
if err:kind() == errors.NOT_FOUND then
    -- 处理资源缺失
end

错误类型

常量 使用场景
errors.NOT_FOUND 资源不存在
errors.ALREADY_EXISTS 资源已存在
errors.INVALID 错误的输入或参数
errors.PERMISSION_DENIED 访问被拒绝
errors.UNAVAILABLE 服务暂时不可用
errors.INTERNAL 内部错误
errors.CANCELED 操作已取消
errors.CONFLICT 资源状态冲突
errors.TIMEOUT 操作超时
errors.RATE_LIMITED 请求过多
errors.UNKNOWN 未指定错误

调用栈

获取结构化调用栈:

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

可重试错误

通常可重试 不可重试
TIMEOUT INVALID
UNAVAILABLE NOT_FOUND
RATE_LIMITED PERMISSION_DENIED
ALREADY_EXISTS
if err:retryable() then
    -- 可以安全重试
end

错误详情

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