错误与调试说明

说明 TRON API 的错误报告机制,介绍 HTTP 层错误、节点预校验错误和链上执行错误,并给出十六进制错误消息解码、请求重试策略和幂等性处理建议。

TRON API 错误需要先按发生阶段分类。不同阶段代表交易处于不同状态,重试策略也不同:

  • HTTP 层错误:请求在到达 TRON 节点前,在网络传输或网关层发生的故障。
  • 校验错误:节点在正式执行交易前,在预校验阶段拒绝了交易。通常通过 CONTRACT_VALIDATE_ERROR 状态码上报,并附带十六进制编码的错误消息
  • 链上执行错误:交易已成功通过校验并被打包进区块,但在链上实际执行时发生失败(如 TVM Revert、资源耗尽等)。这类错误的明细体现在交易回执中,而非接口广播的响应里。
⚠️

注意

生产环境必须区分上述三类错误,并分别处理。混淆错误阶段可能导致严重问题。例如,盲目重试一笔已广播但执行时触发 Revert 的交易,可能在链上状态变化后引发重复操作或业务状态错乱。

📘

前置阅读


1. HTTP 层错误(网络与传输故障)

这类错误通常意味着请求没有完成一次完整往返,客户端没有拿到 TRON 节点返回的 JSON 业务响应。

错误症状可能的原因推荐处理策略
连接被拒绝(Connection Refused)Endpoint 配置错误、目标节点不可用核对请求 URL,或切换至备用节点
5xx 状态码节点端发生过载、网络故障或内部服务器错误建议采用指数退避(Exponential Backoff)机制进行重试。在生产环境中,建议使用稳定的 Endpoint(如自建全节点、成熟的第三方 RPC,或配置多节点负载均衡)
4xx 状态码请求的 URL 路径错误、缺失必要的 HTTP Header、请求体 JSON 格式不合规范等仔细检查并修复客户端的接口调用逻辑与参数构建方式
请求超时 (Timeout)节点负载过大响应缓慢、网络延迟严重或发起了开销过大的复杂查询适当延长客户端的超时阈值并重试。对于高开销的查询,建议进行拆分,或使用 TronGrid 提供的专用扩展 API
401 或 403 状态码缺失或配置了错误的 API Key(仅在通过 TronGrid 接入时出现)参阅 TronGrid 速率限制 配置 API Key
429 状态码触发请求频次限制(仅在通过 TronGrid 接入时出现)采用退避重试,或检查套餐额度并申请调高上限
📘

说明

HTTP 层错误属于纯粹的传输层故障,交易数据尚未被 TRON 节点接收或处理。因此,在此类情况下可以安全地直接重试相同的请求 Payload,不会存在因重复广播导致交易被二次打包执行的风险。


2. 节点预校验错误(CONTRACT_VALIDATE_ERROR

这类错误发生在节点已接收并解析请求之后、交易进入交易内存池(Mempool)之前。也就是说,交易未成功进入网络等待打包。

广播接口返回的失败响应通常如下所示:

{
  "result": false,
  "code": "CONTRACT_VALIDATE_ERROR",
  "message": "636f6e7472616374207061726168657920646f6573206e6f74206d61746368"
}

响应中的 code 字段表示校验失败的粗粒度大类(例如 CONTRACT_VALIDATE_ERRORSIGERRORBANDWITH_ERROR 等)。而导致失败的具体业务原因,则存放在 message 字段中,并以十六进制 Hex 格式进行了编码。

解码十六进制错误消息

为了在开发或日志系统中查看明文错误,需要对 message 进行 Hex 解码:

const hex = "636f6e7472616374207061726168657920646f6573206e6f74206d61746368";
const decoded = Buffer.from(hex, "hex").toString("utf8");
console.log(decoded);
// 输出: "contract parahey does not match"
💡

提示

多数 SDK 会自动解码错误消息。如果日志中出现大段十六进制字符串,通常说明业务直接处理了原始 HTTP API 响应。对外告警或展示给前端用户前,应先完成解码转换。

常见的校验错误类型与解决方案

解码后的明文消息(示例)发生原因推荐解决方案
account does not exist发起交易的签名方账户(或某些特定接口的接收方账户)尚未在链上激活需向该地址转入任意小额 TRX 激活账户
balance is not sufficient账户余额不足以支撑该笔交易所声称的转移金额或资源消耗上限及时充值 TRX
signature error交易签名校验失败常见于编码格式前后不一致(如 visible 标志混用,参见编码指南),或者在构建完交易后,客户端篡改了 raw_data 中的数据字段
Transaction expired交易签名上链时间超过了交易本身的有效限期必须丢弃该交易,从头重新构建并快速完成签名和广播
Validate ... contract error, ...智能合约调用的特定入参校验失败仔细查阅完整的错误消息,这通常由于函数参数的 ABI 编码错误或值不符合要求导致
frozenBalance must be positive质押金额设置为 0 或负数传入合规的正整数(单位为 sun,即 10^-6 TRX)
delegateBalance must be more than 1 TRX资源代理的金额低于系统的最低限制提高代理金额,使其大于或等于 1 TRX
BANDWITH_ERROR交易发送者没有足够的带宽可用质押 TRX 获取带宽,或向账户充入 TRX,在带宽不足时通过燃烧 TRX 支付资源成本。详见资源模型说明

3. 链上执行阶段错误

请记住:交易被打包进区块不等于交易执行成功。交易即使通过节点预校验并记录在链上,仍可能在虚拟机(TVM)执行阶段失败。要确认最终结果,必须查询交易收据(Transaction Receipt):

POST /walletsolidity/gettransactioninfobyid
Content-Type: application/json

{ "value": "<txid>" }

查看返回结构体中的 receipt.result 字段。其完整的状态码枚举定义在底层的 protocol/src/main/protos/core/Tron.proto 文件中,详情如下:

receipt.result 字段值枚举索引具体执行含义
DEFAULT0初始状态(已固化的交易中几乎不会出现此值)
SUCCESS1交易已成功执行
REVERT2智能合约执行异常中断(触发了 REVERT 操作码,即 assertrequire 条件校验失败)
BAD_JUMP_DESTINATION3合约字节码中存在无效的跳转指令
OUT_OF_MEMORY4合约运行中内存分配超限
PRECOMPILED_CONTRACT5预编译合约执行错误
STACK_TOO_SMALL6虚拟机栈下溢错误(尝试从空栈弹出数据)
STACK_TOO_LARGE7虚拟机栈溢出(超出了 1024 层的最大栈限制)
ILLEGAL_OPERATION8合约指令集中包含非法或不被支持的操作码
STACK_OVERFLOW9执行引擎栈空间溢出
OUT_OF_ENERGY10交易在执行过程中耗尽了所配给的能量额度(Energy)
OUT_OF_TIME11交易的计算时间超出了单笔交易的硬性时间限制
JVM_STACK_OVER_FLOW12JVM 级别栈溢出(常见于过深或失控的递归合约调用)
UNKNOWN13其他未被归类的异常或系统内部错误
TRANSFER_FAILED14合约内部发起的 TRX 或 TRC-10 Token 转移操作失败
INVALID_CODE15尝试部署或调用的智能合约字节码格式校验未通过
💡

提示

receipt.result 返回 REVERT 时,可以进一步提取交易响应中 contractResult[0] 字段的数据。该数据遵循 Solidity 标准的 Error(string) 错误信息 ABI 编码格式,经解码后即可还原出合约抛出的具体文字原因(如 "Insufficient allowance")。


业务重试策略

针对不同类别的错误,业务系统应当实施针对性的重试处理方案:

错误类别相同的 Payload 能否直接重试?推荐重试机制与解决步骤
网络级 HTTP 异常推荐使用指数退避(Exponential Backoff)重试机制,每次重试的最大间隔控制在 30 秒内。
5xx 服务端错误退避后进行重试;若节点持续报错,建议在客户端逻辑中执行故障转移,切换至备用 Endpoint。
429 频次限制严格遵守 HTTP 响应头中的 Retry-After 时间后再发起重试,或申请提升 QPS 限制额度。
签名校验错误 (SIGERROR)否(重试无意义)表明签名私钥有误或数据在构建后遭遇了篡改。必须检查并修复本地的编码算法,并重新发起交易构建。
交易过期 (Transaction expired)否(重试必失败)交易有效性已失。必须丢弃此交易,向节点重新发起交易构建、本地签名并再次广播。
余额不足校验错误否(前提是未发生充值)即使重新构建依然会失败。必须先在链上为源地址充值,然后才能重新构建与广播交易。
链上执行失败(REVERT/OUT_OF_ENERGY否(重试仍会失败并消耗资源)这类交易已被链上打包但执行失败。需要诊断失败的业务逻辑(如调高 fee_limit 或排查合约状态),再构建并广播一笔全新的交易。

交易幂等性设计

为 TRON 网络开发高并发支付或写入系统时,需要建立两项幂等与状态确认防线:

  1. 重复广播已签名的相同交易是安全的:TRON 全网通过 txID 做唯一性去重。重复广播完全相同的已签名交易时,节点通常返回相同的 txid,不会导致该交易被打包或执行两次。广播后如果因网络超时或服务端 5xx 未能确认结果,可以重试广播同一笔交易。
  2. 广播成功不等于交易最终落账:成功广播只代表交易进入节点交易内存池。在将资金变化或状态变更视为最终结果前,必须通过 /walletsolidity/gettransactioninfobyid 查询已固化数据,并确认 Receipt 为 SUCCESS

常用调试 Endpoint

Endpoint 路径主要调试用途
/wallet/triggerconstantcontract静态调用合约,无需广播即可进行模拟执行。常用于预估执行所需能量,或在正式发起交易前提前捕获可能发生的 TVM Revert。
/wallet/estimateenergy专用的能量估算接口(自 java-tron 4.7.0.1 起支持),较 triggerconstantcontract 能提供更精确的执行成本预测。
/walletsolidity/gettransactioninfobyid最核心的交易确认接口。用于查验已广播交易的最终回执信息,返回数据来自已固化区块。
/wallet/gettransactioninfobyid同样用于查询交易收据,但读取的是最新区块(链头)。数据生成较快,但在极少数情况下可能受微分叉或链重组影响。
/walletsolidity/getblockbynum通过区块高度抓取已固化的区块数据。常用于充值检测系统(Deposit Indexer)遍历、扫描和核算特定区块中的转账交易。
/wallet/getaccountresource查询特定账户当前的带宽与能量状态,便于估算账户可直接使用的资源。
/wallet/getchainparameters查询当前全网的动态链上参数。当资源价格或解锁等待期发生变化时,可在此查询 getUnfreezeDelayDaysgetEnergyFee 等链上参数。
💡

提示

编写智能合约或开发 DApp 时,建议在正式提交交易前使用 /wallet/triggerconstantcontract 模拟执行。该接口本身不要求传入交易级 fee_limit;可将返回的 energy_used 按当前 getEnergyFee 换算后,与计划设置的 fee_limit 比较,从而提前发现预算过低的风险。


相关资源