Skip to content
Skills Library
Programming · Analysis

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.

Licence
Apache-2.0
Last repository change
23.10.2026

Assessment and security

100/ 100Class: good
Format25 / 25
Frontmatter with name and description, valid name, description up to 1,024 characters, name matching the folder.
Discoverability25 / 25
Description explains when to use the skill, has a reasonable length and uses third person.
Content35 / 35
At least 150 words and at most 500 lines, headings, step lists, examples or code.
Hygiene15 / 15
No placeholders such as TODO, no Windows paths, with a licence.
Riskno signals detected in the scan
Files in this package
1
Scripts
0
HTML comments
0
URLs in SKILL.md
2
Deprecation

No signals detected. Repository changed on 23.10.2026, without references to retired models or APIs.

Licence

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

  1. When to Use
  2. Input Parameters
  3. Debugging Workflow
  4. Common Root Causes
  5. Decoding Revert Selectors
  6. Domain ID Reference
  7. Example Investigation
Original SKILL.md headings · 197 lines, 1,005 words
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.

Feedback and reports

Your message goes to Bartosz Sokoliński. An email address is needed only for a reply. See the privacy policy.