debug-message
/debug-message
Debug why a Hyperlane message is not being processed. Use when given a message ID or explorer URL to investigate delivery failures, gas estimation errors, validator issues, or other processing problems.
- Author
- hyperlane-xyz ↗
- Repository
- hyperlane-monorepo ↗
- Licence
- Apache-2.0
- Last repository change
- 23.10.2026
Assessment and security
- Files in this package
- 1
- Scripts
- 0
- HTML comments
- 0
- URLs in SKILL.md
- 2
No signals detected. Repository changed on 23.10.2026, without references to retired models or APIs.
Apache-2.0, otwarta: można używać i zmieniać, z zachowaniem licencji i informacji o zmianach.
What it does and when to use it
Debug why a Hyperlane message is not being processed. Use when given a message ID or explorer URL to investigate delivery failures, gas estimation errors, validator issues, or other processing problems.
Original author description
Debug why a Hyperlane message is not being processed. Use when given a message ID or explorer URL to investigate delivery failures, gas estimation errors, validator issues, or other processing problems.
How it works
- When to Use
- Input Parameters
- Debugging Workflow
- Common Root Causes
- Decoding Revert Selectors
- Domain ID Reference
- Example Investigation
SKILL.md preview
---
name: debug-message
description:
Debug why a Hyperlane message is not being processed. Use when given
a message ID or explorer URL to investigate delivery failures, gas estimation errors,
validator issues, or other processing problems.
---
# Debug Hyperlane Message Skill
## When to Use
- User provides a message ID (e.g., `0xa454...`) or explorer URL
- Investigating why a message is stuck or not delivered
- Debugging gas estimation failures
- Understanding message processing status
## Input Parameters
| Parameter | Required | Example | Description |
| -------------- | -------- | ---------------------------------------------- | ------------------------------- |
| `message_id` | Yes | `0xa454559c...` | The 66-character hex message ID |
| `explorer_url` | Optional | `https://explorer.hyperlane.xyz/message/0x...` | Can extract message_id from URL |
## Debugging Workflow
### Step 1: Get Basic Message Details from Explorer
Fetch the explorer page to get origin/destination chains and basic status:
```
WebFetch: https://explorer.hyperlane.xyz/message/[MESSAGE_ID]
Prompt: Extract message status, origin chain, destination chain, sender, recipient, timestamp, delivery status
```
Key info to extract:
- Origin chain and domain ID
- Destination chain and domain ID
- Is it delivered? (if yes, no debugging needed)
- Timestamp (how old is it?)
### Step 2: Search Relayer Logs for the Message
Use the gcloud CLI to find logs related to this message in the omniscient relayer:
```bash
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
```
### Step 3: Identify the Message Status
Look for the message in `PendingMessage` entries. Common statuses:
| Status | Meaning | Priority |
| ------------------------------------ | ---------------------------------------- | ------------------------ |
| `Retry(ErrorEstimatingGas)` | Gas estimation failing - contract revert | HIGH |
| `Retry(GasPaymentRequirementNotMet)` | Insufficient gas payment | MEDIUM |
| `Retry(CouldNotFetchMetadata)` | Validator signatures unavailable | LOW (check after 5+ min) |
| `FirstPrepareAttempt` | Still processing, not stuck yet | LOW |
Extract status with:
```bash
grep -o "message_id: [MESSAGE_ID][^}]*" [log_output] | sort -u
```
### Step 4: Check for Gas Payment Issues
If message is slow/stuck, search for gas payment evaluation logs:
```bash
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
```
Key fields in `jsonPayload.fields`:
- `current_payment.gas_amount` - gas units paid for by sender
- `tx_cost_estimate.gas_limit` - gas units needed for delivery
- `current_expenditure.gas_used` - gas already spent on retries
- `policy` - subsidy policy (e.g., `fractional_numerator: 1, fractional_denominator: 2` = 50% subsidy)
If `gas_amount < gas_limit`, message fails with `"Repreparing message: Gas payment requirement not met"` and retries every ~3 minutes.
### Step 5: For Gas Estimation Errors - Get the Revert Reason
If status is `ErrorEstimatingGas`, the actual revert reason is in `jsonPayload.fields.error`. Use this query and extraction:
```bash
# Query logs with error field
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
```
The error field contains the full revert reason, e.g.:
```
"error": "ContractError(...JsonRpcError { code: 3, message: \"execution reverted: panic: arithmetic underflow or overflow (0x11)\", data: Some(...) }...)"
```
**Quick extraction** - pipe to extract just the revert message:
```bash
... | grep -oP 'execution reverted: [^"\\]+' | head -1
```
Common revert patterns:
- `execution reverted: panic: arithmetic underflow or overflow (0x11)` - Contract math error
- `execution reverted: [CUSTOM_ERROR]` - Custom contract revert (decode with `cast 4byte`)
- `execution reverted` with hex data - Decode selector with `cast 4byte 0x[first4bytes]`
### Step 6: Extract Message Details
From the logs, identify:
- `origin`: Source chain
- `destination`: Destination chain (or domain ID like `4114` for Citrea)
- `sender`: Origin contract address
- `recipient`: Destination contract address (the warp route or recipient)
- `nonce`: Message sequence number
Example log format:
```
HyperlaneMessage { id: 0x..., nonce: 162898, origin: ethereum, sender: 0x..., destination: 4114, recipient: 0x... }
```
### Step 7: Report Findings
Summarize:
1. **Message ID**: Full ID
2. **Route**: Origin -> Destination (e.g., Ethereum -> Citrea)
3. **Status**: Current processing status
4. **Root Cause**: The actual error (e.g., contract revert reason)
5. **Retry Count**: How many times it's been attempted
6. **Recommendation**: What needs to happen (e.g., fix recipient contract, wait for validators)
## Common Root Causes
### Gas Estimation Errors
| Error | Meaning | Resolution |
| ------------------------------------------------ | ---------------------- | ------------------------- |
| `panic: arithmetic underflow or overflow (0x11)` | Contract math error | Bug in recipient contract |
| `IXERC20_NotHighEnoughLimits()` | Bridge rate limit hit | Wait for limit reset |
| `InsufficientBalance` | Not enough tokens | Fund the contract |
| `Unauthorized` | Access control failure | Check permissions |
### Metadata/Validator Issues
If `CouldNotFetchMetadata` persists > 5 minutes:
1. Check validator status using the `debug-validator-checkpoint-inconsistency` skill
2. Identify if validators are behind on the origin chain
### Gas Payment Issues
If `GasPaymentRequirementNotMet`:
- Compare `current_payment.gas_amount` vs `tx_cost_estimate.gas_limit`
- Message will auto-retry every ~3 min until gas prices drop or subsidy kicks in
- Check `policy` field for subsidy ratio (e.g., 1/2 = relayer covers 50%)
- Resolution: wait for gas prices to drop, or manually subsidize via IGP top-up
## Decoding Revert Selectors
When you see hex revert data like `0x4e487b71...`:
```bash
cast 4byte 0x4e487b71
# Returns: Panic(uint256)
```
Common panic codes:
- `0x11` - Arithmetic overflow/underflow
- `0x12` - Division by zero
- `0x21` - Invalid enum value
- `0x31` - Pop on empty array
- `0x32` - Array out of bounds
## Domain ID Reference
Common domain IDs (destination field in logs):
- `1` - Ethereum
- `42161` - Arbitrum
- `10` - Optimism
- `137` - Polygon
- `4114` - Citrea
Check `@hyperlane-xyz/registry` or chain metadata for full mapping.
## Example Investigation
User asks: "Why isn't message 0xa454... being processed?"
1. Fetch explorer: Origin=Ethereum, Dest=Citrea, not delivered
2. Query relayer logs for `0xa454...`
3. Find status: `Retry(ErrorEstimatingGas)`
4. Search error logs: `execution reverted: panic: arithmetic underflow or overflow (0x11)`
5. Report: "Message from Ethereum to Citrea is failing because the recipient contract (0xbd39...) on Citrea is reverting with an arithmetic overflow error. This is a bug in the destination contract that needs to be fixed by the contract owner."
Versions
The database has no other skills named debug-message.
Database snapshot: 13.11.2026 · package version ca60a0d8ff1b (SHA-256 digest of the entire package)
Downloads in the last 30 days: 0 · ranking
Report a problem with this skill: harmful content, incorrect descriptions or an author’s removal request.
Similar skills
- 100hyperlane-message-utils
Encode and decode raw Hyperlane messages to/from packed hex bytes using the CLI. Use when you need to construct a message for testing, inspect a raw message from logs or a transaction, or decode a warp transfer body. - 90code-review
Review code changes using Hyperlane Warp UI coding standards. Use when reviewing PRs, checking your own changes, or doing self-review before committing. - 90code-review
Review code changes using Hyperlane monorepo coding standards. Use when reviewing PRs, checking your own changes, or doing self-review before committing. - 90debug
This skill should be used when the user runs /touchdesigner:debug or asks to debug, investigate, or find TouchDesigner node errors — trigger phrases include "debug my TouchDesigner project", "why is this node broken", "find errors in TD", "investigate node errors", "what's wrong… - 100customerio-common-errors
Diagnose and fix Customer.io common errors. Use when troubleshooting API errors, delivery failures, campaign issues, or SDK exceptions. Trigger: "customer.io error", "customer.io not working", "debug customer.io", "customer.io 401", "customer.io 429". - 100output-debug-workflow
Debug Output SDK workflow issues. Use when user reports a workflow failing, erroring, hanging, producing wrong results, or asks to debug, troubleshoot, or investigate a workflow execution.