错误码
每个错误都有稳定的错误码。SDK 使用相同的错误码(Unity 中为枚举),另外还有几个错误码用于请求到达服务器之前发生的问题。
代码注释和 API 名称保留英文,以便与 SDK 保持一致。
本页内容
API 错误#
| 错误码 | HTTP | Unity | 何时出现 | 可重试? |
|---|---|---|---|---|
validation | 400, 422 | Validation | 输入无效;details.fields 会指出具体字段。 | 否 |
unauthorized | 401 | Unauthorized | 密钥错误,或玩家令牌缺失、过期或已被撤销。 | 否 |
forbidden | 403 | Forbidden | 项目已暂停、端点仅限服务器调用,或必须使用 HTTPS。 | 否 |
plan_limit | 403 | PlanLimit | 已达到套餐上限(玩家、条目、存储空间等)。不会删除任何数据。 | 否 |
not_found | 404 | NotFound | 未知的端点、排行榜、玩家或存档键。 | 否 |
conflict | 409 | Conflict | 操作已完成,例如本周期的奖励已经领取。 | 否 |
revision_mismatch | 409 | RevisionMismatch | 云存档已在另一台设备上被修改。 | 否 |
rate_limited | 429 | RateLimited | 每分钟请求过多,或处于排行榜冷却时间内。请等待 Retry-After 秒。 | 是 |
quota_exceeded | 429 | QuotaExceeded | 账号的每日请求配额已用完;将于 00:00 UTC 重置。 | 否 |
server_error | 500 | ServerError | 服务器出现故障。SDK 会自动重试安全请求。 | 是 |
仅限 SDK 的错误#
| 错误码 | HTTP | Unity | 何时出现 | 可重试? |
|---|---|---|---|---|
network | — | Network | 无法连接服务器。 | 是 |
timeout | — | Timeout | 请求耗时超过了超时时间。 | 是 |
not_configured | — | NotConfigured | 基础 URL、项目 ID 或客户端密钥缺失或无效。 | 否 |
not_signed_in | — | NotSignedIn | 在登录前或会话过期后发起了玩家调用。 | 否 |
signature_invalid | — | SignatureInvalid | 远程配置未通过验证,因此未被使用。 | 否 |
parse_error | — | ParseError | 无法读取响应(通常是代理或 HTML 错误页面导致的)。 | 否 |
link_expired | — | LinkExpired | 账号关联页面已过期;请重新开始。 | 否 |
link_cancelled | — | LinkCancelled | 账号关联流程已取消。 | 否 |
处理错误#
message 是给开发者看的,不要展示给玩家;请根据错误码进行判断。只重试可重试的错误,并记录请求 ID,以便在日志页面中找到对应的请求。
var top = await Majacloud.Leaderboards.GetTopAsync("coins", 10);
if (top.Ok)
{
foreach (var entry in top.Value.Entries)
Debug.Log($"#{entry.Rank} {entry.PlayerName} {entry.Score}");
}
else if (top.Error.IsRetryable)
{
// Network, timeout, 5xx or rate limit: try again later
Debug.Log("Retry in " + top.Error.RetryAfterSeconds + " s");
}
else
{
Debug.LogWarning(top.Error.Code + ": " + top.Error.Message + " (" + top.Error.RequestId + ")");
}var top := await Majacloud.leaderboards.get_top("coins", 10)
if top.ok:
for entry in top.value.entries:
print("#%d %s %d" % [entry.rank, entry.player_name, entry.score])
elif top.is_retryable():
# Network, timeout, 5xx or rate limit: try again later
print("Retry in ", top.retry_after, " s")
else:
push_warning("%s: %s (%s)" % [top.error, top.message, top.request_id])const top = await mc.leaderboards.getTop('coins', { limit: 10 });
if (top.ok) {
for (const entry of top.value.entries) {
console.log(`#${entry.rank} ${entry.player_name} ${entry.score}`);
}
} else if (top.error.retryable) {
// Network, timeout, 5xx or rate limit: try again later
console.log('Retry in', top.error.retryAfter, 's');
} else {
console.warn(`${top.error.code}: ${top.error.message} (${top.error.requestId})`);
}// Success
{ "ok": true, "entries": [ … ], "total": 42 }
// Error (HTTP 4xx/5xx)
{
"ok": false,
"error": {
"code": "rate_limited",
"message": "Project rate limit reached. Try again in a minute.",
"request_id": "6f1c2a9e-…",
"details": { "limit": 120, "window": "minute" }
}
}