Skip to content

错误码参考

本文档汇总 Shield runtime error 的稳定错误码,是错误码的权威来源。业务错误不由本文档统一分配。

错误对象结构

所有 runtime 错误通过 ok == false 返回,第二个返回值是 Error 对象:

lua
{
  code = "timeout",           -- 错误码(本文档定义)
  message = "call timeout",   -- 人类可读描述
  source = "runtime",         -- 来源:runtime | data | network
  retryable = false,          -- 是否建议重试
  detail = nil,               -- 可选调试信息
}

规则:

  • 本文档只定义 runtime/framework 错误。
  • shield.call 成功返回时,后续返回值全部属于 callee 的业务契约,不由 runtime 解释。
  • 旧 API 删除后的报错也使用本文档中的稳定错误码。

一、消息与服务错误

shield.send / shield.call / shield.spawn 产生的错误。

错误码来源说明retryable
invalid_targetsend/call目标格式错误(非 handle 且非合法 name)
invalid_methodsend/call方法名非法(空、过长、含非法字符)
invalid_service_modulespawnLua 文件未返回合法 service module table
script_load_failedspawnLua 文件语法错误、load 失败或顶层代码抛错
invalid_namespawn服务名不合法(格式、长度、保留前缀)
name_conflictspawn服务名已被占用
encode_failedsend/call消息编码失败(类型不支持、嵌套过深、循环引用)
message_too_largesend/call消息体积超过 max_message_size(默认 1MB)
service_not_foundsend/call目标服务不存在(name 未注册或 handle 已失效)
service_deadsend/call目标服务已停止
node_offlinesend/call目标节点离线(集群场景)
mailbox_fullsend目标服务 mailbox 达到上限
init_failedspawnon_init 返回失败或抛出异常
spawn_timeoutspawn服务初始化超过 spawn_timeout(默认 10s)
runtime_stoppingsend/call/spawn运行时正在关闭
permission_deniedsend/call/spawn权限不足
timeoutcall调用超时(默认 5s)
method_not_foundcall目标服务没有该方法
handler_errorcall目标服务 method 抛出未捕获异常
context_expiredcontexthandler 已返回,shield.sender/trace/deadline 上下文失效
api_not_allowed_in_exitexit hookon_exit 中调用了会挂起的 API
legacy_api_removedlegacy API调用了已删除的旧 API

二、资源限制错误

服务级资源超限产生的错误。

错误码说明默认上限
mailbox_full单个 service mailbox 消息数超限10000
coroutine_limit单个 service coroutine 数超限1000
pending_call_limit单个 service 待响应 call 数超限1000
timer_limit单个 service timer 数超限10000
fork_limit单个 service fork task 数超限1000

三、数据库错误

shield.db.* 产生的错误。

错误码说明retryable
module_unavailabledatabase 模块未启用
db_query_failed未分类的数据库执行失败视具体驱动
connection_lost数据库连接丢失
connection_timeout建立连接超时
query_timeout查询超时
syntax_errorSQL 语法错误
constraint_violation约束违反(唯一键、外键等)
transaction_aborted事务中止
pool_exhausted连接池耗尽

四、Redis 错误

shield.redis.* / shield.global() 等 Redis 相关 API 产生的错误。

错误码说明retryable
module_unavailableredis 模块未启用
redis_command_failed未分类的 Redis 命令失败视具体驱动
connection_lostRedis 连接丢失
connection_timeout建立连接超时
command_timeout命令执行超时
wrong_typeRedis 类型错误(如对 String 执行 List 操作)
pool_exhausted连接池耗尽

五、网络错误

shield_net / SessionHandle 相关的错误。

错误码说明retryable
session_closedsession 已关闭,handle stale
session_send_queue_fullsession 发送队列已满
handshake_timeout握手超时
decode_error协议解码错误
connection_limit连接数达到上限
ip_limit单 IP 连接数达到上限

六、错误处理建议

重试策略

lua
function M.call_with_retry(target, method, data, max_retries)
    max_retries = max_retries or 3
    local retries = 0

    while retries < max_retries do
        local ok, result = shield.call(target, method, data)
        if ok then
            return true, result
        end

        if result.retryable then
            retries = retries + 1
            if retries < max_retries then
                shield.sleep(100 * retries)  -- 指数退避
            end
        else
            return false, result
        end
    end

    return false, {
        code = "max_retries_exceeded",
        message = "Max retries exceeded",
        source = "runtime",
        retryable = false,
    }
end

错误日志

lua
-- Runtime 错误
shield.log.error(string.format(
    "[runtime] %s: target=%s method=%s code=%s message=%s",
    "call_failed", target, method, err.code, err.message
))

-- 业务错误
shield.log.warn(string.format(
    "[business] %s: target=%s method=%s code=%s message=%s",
    "business_error", target, method, err.code, err.message
))

业务错误

业务错误属于 callee 自己的返回契约,不使用 ok == false 传递:

lua
-- Callee
function M.get_player(uid)
    local player = find_player(uid)
    if not player then
        return {
            ok = false,
            code = "PLAYER_NOT_FOUND",
            message = "Player not found",
        }
    end

    return {
        ok = true,
        player = player,
    }
end

-- Caller
local ok, result = shield.call("player", "get_player", uid)
if not ok then
    -- Runtime 错误(本文档定义的错误码)
    shield.log.error("runtime error: " .. result.code)
elseif not result.ok then
    -- 业务错误,由业务自己定义
    shield.log.warn("business error: " .. result.code)
else
    process_player(result.player)
end

Apache License 2.0