name: debug-message description: 调试为什么Hyperlane消息未被处理。当提供消息ID或探索器URL时使用,以调查交付失败、Gas估计错误、验证器问题或其他处理问题。
调试Hyperlane消息技能
何时使用
- 用户提供消息ID(例如
0xa454...)或探索器URL - 调查消息为何卡住或未交付
- 调试Gas估计失败
- 理解消息处理状态
输入参数
| 参数 | 必需 | 示例 | 描述 |
|---|---|---|---|
message_id |
是 | 0xa454559c... |
66个字符的十六进制消息ID |
explorer_url |
可选 | https://explorer.hyperlane.xyz/message/0x... |
可以从URL提取消息ID |
调试工作流程
步骤1:从探索器获取基本消息详情
获取探索器页面以获取起源/目标链和基本状态:
WebFetch: https://explorer.hyperlane.xyz/message/[MESSAGE_ID]
Prompt: 提取消息状态、起源链、目标链、发送者、接收者、时间戳、交付状态
关键信息提取:
- 起源链和域ID
- 目标链和域ID
- 是否已交付?(如果是,则无需调试)
- 时间戳(消息已存在多久?)
步骤2:在Relayer日志中搜索该消息
使用gcloud CLI在omniscient relayer中查找与此消息相关的日志:
gcloud logging read 'resource.type="k8s_container" AND resource.labels.project_id="abacus-labs-dev" AND resource.labels.location="us-east1-c" AND resource.labels.cluster_name="hyperlane-mainnet" AND resource.labels.namespace_name="mainnet3" AND labels.k8s-pod/app_kubernetes_io/component="relayer" AND labels.k8s-pod/app_kubernetes_io/instance="omniscient-relayer" AND labels.k8s-pod/app_kubernetes_io/name="hyperlane-agent" AND "[MESSAGE_ID]"' --project=abacus-labs-dev --limit=50 --format=json --freshness=1d
步骤3:识别消息状态
在PendingMessage条目中查找消息。常见状态:
| 状态 | 含义 | 优先级 |
|---|---|---|
Retry(ErrorEstimatingGas) |
Gas估计失败 - 合约回滚 | 高 |
Retry(GasPaymentRequirementNotMet) |
Gas支付不足 | 中 |
Retry(CouldNotFetchMetadata) |
验证器签名不可用 | 低(5分钟后检查) |
FirstPrepareAttempt |
仍在处理,尚未卡住 | 低 |
使用以下命令提取状态:
grep -o "message_id: [MESSAGE_ID][^}]*" [log_output] | sort -u
步骤4:检查Gas支付问题
如果消息缓慢/卡住,搜索Gas支付评估日志:
gcloud logging read '[BASE_RELAYER_QUERY] AND "[MESSAGE_ID]" AND jsonPayload.fields.message:"Evaluating if message meets gas payment requirement"' --project=abacus-labs-dev --limit=5 --format=json --freshness=7d
jsonPayload.fields中的关键字段:
current_payment.gas_amount- 发送者支付的Gas单位tx_cost_estimate.gas_limit- 交付所需的Gas单位current_expenditure.gas_used- 已在重试上花费的Gaspolicy- 补贴政策(例如fractional_numerator: 1, fractional_denominator: 2= 50%补贴)
如果 gas_amount < gas_limit,消息会失败并显示 "Repreparing message: Gas payment requirement not met",每约3分钟重试一次。
步骤5:对于Gas估计错误 - 获取回滚原因
如果状态是 ErrorEstimatingGas,实际回滚原因在 jsonPayload.fields.error 中。使用此查询和提取:
# 查询带有错误字段的日志
gcloud logging read 'resource.type="k8s_container" AND resource.labels.project_id="abacus-labs-dev" AND resource.labels.location="us-east1-c" AND resource.labels.cluster_name="hyperlane-mainnet" AND resource.labels.namespace_name="mainnet3" AND labels.k8s-pod/app_kubernetes_io/component="relayer" AND labels.k8s-pod/app_kubernetes_io/instance="omniscient-relayer" AND labels.k8s-pod/app_kubernetes_io/name="hyperlane-agent" AND "[MESSAGE_ID]" AND jsonPayload.fields.error:*' --project=abacus-labs-dev --limit=5 --format=json --freshness=1d 2>/dev/null | grep -o '"error": "[^"]*"' | head -1
错误字段包含完整的回滚原因,例如:
"error": "ContractError(...JsonRpcError { code: 3, message: \"execution reverted: panic: arithmetic underflow or overflow (0x11)\", data: Some(...) }...)"
快速提取 - 通过管道提取仅回滚消息:
... | grep -oP 'execution reverted: [^"\\]+' | head -1
常见回滚模式:
execution reverted: panic: arithmetic underflow or overflow (0x11)- 合约数学错误execution reverted: [CUSTOM_ERROR]- 自定义合约回滚(使用cast 4byte解码)execution reverted带有十六进制数据 - 使用cast 4byte 0x[first4bytes]解码选择器
步骤6:提取消息详情
从日志中识别:
origin: 源链destination: 目标链(或域ID,如Citrea的4114)sender: 起源合约地址recipient: 目标合约地址(warp路由或接收者)nonce: 消息序列号
日志格式示例:
HyperlaneMessage { id: 0x..., nonce: 162898, origin: ethereum, sender: 0x..., destination: 4114, recipient: 0x... }
步骤7:报告发现
总结:
- 消息ID:完整ID
- 路由:起源 -> 目标(例如,Ethereum -> Citrea)
- 状态:当前处理状态
- 根本原因:实际错误(例如,合约回滚原因)
- 重试计数:已尝试次数
- 建议:需要采取的措施(例如,修复接收者合约、等待验证器)
常见根本原因
Gas估计错误
| 错误 | 含义 | 解决方案 |
|---|---|---|
panic: arithmetic underflow or overflow (0x11) |
合约数学错误 | 修复接收者合约中的错误 |
IXERC20_NotHighEnoughLimits() |
桥接速率限制达到 | 等待限制重置 |
InsufficientBalance |
代币不足 | 资助合约 |
Unauthorized |
访问控制失败 | 检查权限 |
元数据/验证器问题
如果 CouldNotFetchMetadata 持续超过5分钟:
- 使用
debug-validator-checkpoint-inconsistency技能检查验证器状态 - 识别验证器是否在起源链上落后
Gas支付问题
如果 GasPaymentRequirementNotMet:
- 比较
current_payment.gas_amount与tx_cost_estimate.gas_limit - 消息将每约3分钟自动重试,直到Gas价格下降或补贴生效
- 检查
policy字段的补贴比例(例如,1/2 = relayer覆盖50%) - 解决方案:等待Gas价格下降,或通过IGP充值手动补贴
解码回滚选择器
当看到十六进制回滚数据如 0x4e487b71...:
cast 4byte 0x4e487b71
# 返回:Panic(uint256)
常见panic代码:
0x11- 算术溢出/下溢0x12- 除以零0x21- 无效枚举值0x31- 空数组上的pop操作0x32- 数组越界
域ID参考
常见域ID(日志中的destination字段):
1- Ethereum42161- Arbitrum10- Optimism137- Polygon4114- Citrea
检查 @hyperlane-xyz/registry 或链元数据以获取完整映射。
示例调查
用户问:“为什么消息 0xa454… 未被处理?”
- 获取探索器:起源=Ethereum,目标=Citrea,未交付
- 查询relayer日志获取
0xa454... - 查找状态:
Retry(ErrorEstimatingGas) - 搜索错误日志:
execution reverted: panic: arithmetic underflow or overflow (0x11) - 报告:“从Ethereum到Citrea的消息失败,因为Citrea上的接收者合约(0xbd39…)以算术溢出错误回滚。这是目标合约中的错误,需要合约所有者修复。”