Skip to content

错误码与排查

程序判断 error_code,开发者查看 message,平台用 trace_id 定位日志。 不要解析错误文案,不要看到401就循环获取令牌。

统一响应

json
{
  "code": 401,
  "error_code": "INVALID_SIGNATURE",
  "message": "request signature verification failed",
  "trace_id": "0123456789abcdef0123456789abcdef"
}
字段类型含义
codeinteger与 HTTP 状态相同;成功为0
error_codestring稳定的错误分类,见下表
messagestring本次失败说明,参数错误通常指出字段;内容可能细化,不作为枚举
trace_idstring本次 HTTP 请求追踪编号,与响应头 X-Trace-Id 相同

错误没有 data。trace_id 由平台自动生成,你无需传入;它不同于写操作的 request_id。合法业务请求的404/405也使用此 JSON 格式。反向代理、网关或断网仍可能产生非 JSON 响应,客户端不能把解析失败当作成功。

错误码和下一步

HTTPerror_code含义接入方处理
400INVALID_ARGUMENT业务字段、JSON、路径、类型或格式错误按 message 和接口参数表修改,重新签名
400COLLECTION_ADDRESS_MANAGED归集目标是平台内的钱包,可能造成循环归集换成由你控制的平台外 TRON 地址后重新签名;当前租户和其他租户的钱包均禁止,不要原样重试
400INVALID_AUTH_HEADER认证头缺失或重复每个认证头只发送一次;不要重复附加
401INVALID_SIGNATURE请求签名不匹配,或 appID/密钥组合无效检查密钥和签名输入;不要刷新令牌掩盖签名错误
401TIMESTAMP_OUT_OF_RANGE时间戳与服务器相差超过300秒校准服务端时间,使用当前秒级时间戳重新签名
401TOKEN_INVALID_OR_EXPIRED令牌缺失、过期、被替换、撤销或与当前 appID 不匹配先读共享缓存中的最新令牌;必要时由单一刷新流程获取
403TENANT_UNAVAILABLE租户停用、删除或到期联系平台处理租户状态,停止重试
404RESOURCE_NOT_FOUND当前租户下没有该对象检查 ID、所属账户及所用的 API 域名;不会透露其他租户资源
404ROUTE_NOT_FOUND接口地址不存在使用平台提供的 API 域名及 /open/v1 路径,核对接口目录
405METHOD_NOT_ALLOWEDHTTP 方法错误按接口页使用 GET 或 POST
409IDEMPOTENCY_CONFLICT同一 request_id 已用于不同业务参数找回原请求;重试用原编号和原参数,新业务才用新编号
409BUSINESS_CONFLICT当前状态不允许操作或记录已存在查看 message,先查询当前状态,再决定是否发起新业务
413PAYLOAD_TOO_LARGE请求体超过1 MiB减小批次;不要把同一请求拆分后继续复用旧编号
429RATE_LIMITED获取令牌或业务请求超过限频按 Retry-After 指定的秒数等待,再重新签名
503SERVICE_BUSY服务并发已满按 Retry-After 等待,减少并行请求
503SERVICE_UNAVAILABLE当前业务依赖不可用保存错误,稍后查询状态;必要时提供 trace_id 给平台
504REQUEST_TIMEOUT服务器处理超时,写入结果可能未知先查询结果;重试必须保持原 request_id 和参数
500INTERNAL_ERROR内部操作失败保存 trace_id 和请求时间;不要改编号重复发起支出

批量接口的 HTTP200/code0 不代表每项都成功。查看 items[].status 和 reason。任务的 failed 与 HTTP 请求错误是两层结果,详见状态与处理

签名错误

按顺序检查:

  1. appID 和密钥是否属于同一租户,是否刚重置过密钥。
  2. 使用 HMAC-SHA256,输出64位小写十六进制。
  3. 方法使用大写;路径完整包含 /open/v1,不包含域名、查询串或末尾斜杠。
  4. 七行末尾均为 LF,最后一行也有 LF;不是 CRLF 或两个字符的反斜杠 n。
  5. 签名使用的 token 原文与 Authorization 中一致,不把 Bearer 放进签名。
  6. 查询串键排序,空格用 %20,加号用 %2B;请求体只序列化一次。
  7. secret 按 UTF-8 使用,不做 hex 解码;空请求体按空字节做 SHA-256。

先运行离线测试。不要上传密钥、完整 token 或签名原文;trace_id 足以协助平台查日志。

令牌问题

新令牌立即撤销旧令牌。若多个服务同时获取令牌,它们会互相使令牌失效。统一缓存并使用互斥锁刷新;收到 TOKEN_INVALID_OR_EXPIRED 时,先确认共享缓存是否已有更新值。

签名错误和时间错误不需要重新申请 token。修正问题后重新生成当前请求签名即可。SDK 不自动刷新或重新执行资金操作,避免重复支出。

写操作超时如何处理

没有收到成功响应,并不能证明写入失败。保留原 request_id 和业务参数,先查已有结果;需要重试时只更新 token、时间戳和签名,业务编号与内容不变。返回过的批量受理结果会按原样重放,查询任务详情才能获得最新状态。

限频和响应头

范围当前规则
获取令牌,同一IP60次 / 300秒
获取令牌,同一appID20次 / 300秒
业务请求,同一租户600次 / 60秒
请求繁忙收到 SERVICE_BUSY 时按 Retry-After 等待,并减少并行请求

429携带 Retry-After。并发限制触发的 SERVICE_BUSY 也携带 Retry-After;不是所有503都会带此头。

示例客户端的错误属性

Node.js ApiError 提供 status、errorCode、traceId、retryAfter、response;Python 对应 status、error_code、trace_id、retry_after、response。

js
import { Client, ApiError } from './client.mjs';
const client = new Client(
  process.env.GUIJI_BASE_URL,
  process.env.GUIJI_APP_ID,
  process.env.GUIJI_APP_SECRET
);
try {
  const data = await client.call(
    process.env.GUIJI_ACCESS_TOKEN, 'GET', '/open/v1/wallets',
    { page: '1', page_size: '20' }, null
  );
  console.log(JSON.stringify(data, null, 2));
} catch (error) {
  if (error instanceof ApiError) {
    console.error({
      http: error.status, error_code: error.errorCode,
      message: error.message, trace_id: error.traceId,
      retry_after: error.retryAfter
    });
  } else {
    console.error('请求未取得结果,请保留原业务编号并先查询状态。');
  }
}

仍无法解决时提供什么

提供:trace_id、请求时间及所在时区、HTTP方法、接口路径、HTTP状态和完整错误响应。写操作另提供 request_id、相关钱包或任务ID。不要提供密钥或 token。