Apply fixes for merkle root mismatch issues in the relayer database. Use after running /investigate-merkle-root-mismatch to investigate and identify the mismatched entries. Requires user confirmation before any database modifications.
Scanned 9/12/2026
Install to Claude Code
npx -y skills add hyperlane-xyz/hyperlane-monorepo --skill fix-merkle-root-mismatch --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Fix Merkle Root Mismatch?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/hyperlane-xyz-fix-merkle-root-mismatch)More formats (shields.io, HTML) on the badges page.
---
name: fix-merkle-root-mismatch
description: Apply fixes for merkle root mismatch issues in the relayer database. Use after running /investigate-merkle-root-mismatch to investigate and identify the mismatched entries. Requires user confirmation before any database modifications.
---
# Fix Merkle Root Mismatch
## When to Use
Use this skill AFTER running `/investigate-merkle-root-mismatch` to investigate the issue.
1. **User request triggers:**
- "Fix the merkle root mismatch on [chain]"
- "Apply the merkle tree fixes"
- "Update the relayer database with correct message IDs"
## Input Parameters
| Parameter | Required | Default | Description |
| ------------------------ | -------- | ---------- | --------------------------------------------------------------- |
| `origin` | Yes | - | The origin chain to fix (e.g., `polygonzkevm`, `ethereum`) |
| `domain_id` | Yes | - | Domain ID of the chain |
| `environment` | No | `mainnet3` | `mainnet3` or `testnet4` |
| `merkle_tree_insertions` | Yes | - | List of corrections: `[{leaf_index, message_id, block_number}]` |
## Prerequisites
1. **Investigation completed** - Run `/investigate-merkle-root-mismatch` first to identify mismatched entries
2. `kubectl` access to the relayer pods
3. Port-forward already established to relayer (port 9090)
## Fix Workflow
### Step 0: Find Monorepo Root
```bash
MONOREPO_ROOT=$(git rev-parse --show-toplevel)
```
### Step 1: Verify Port-Forward is Active
Check if port 9090 is already in use:
```bash
lsof -i :9090
```
If not in use, start port-forward in background:
```bash
kubectl port-forward omniscient-relayer-hyperlane-agent-relayer-0 9090:9090 -n [environment] &
```
Wait a few seconds, then verify it's working:
```bash
curl -s "localhost:9090/merkle_tree_insertions?domain_id=[domain_id]&leaf_index_start=0&leaf_index_end=1"
```
### Step 2: Present Changes for Confirmation
**IMPORTANT: User confirmation required before executing.**
Before making any changes to the relayer database, you MUST:
1. Present a summary of ALL changes to be made in a clear table format:
| Leaf Index | Correct Message ID | Block Number |
| ---------- | ------------------------------------------------------------------ | ------------ |
| 1477 | 0x4bb3e20db45366a6a360ad2639c5421ea622a69b89b2edb045aa97e2051529b7 | 9891832 |
| 1478 | 0xa66dbdc1874acfddf14e75e6a20dd1632e9e3206c5f5855884da0d26d8ca12fa | 9891872 |
2. Use `AskUserQuestion` to get explicit confirmation:
- Question: "Do you want to apply these merkle tree fixes to the relayer database?"
- Options: "Yes, apply fixes" / "No, cancel"
3. **Only proceed if the user explicitly confirms.**
### Step 3: Apply Merkle Tree Fixes
Once confirmed, insert the correct merkle tree insertions via the relayer API:
```bash
curl -X POST \
-H 'Content-type: application/json' \
'localhost:9090/merkle_tree_insertions' \
-d '{
"merkle_tree_insertions": [
{
"chain": [domain_id],
"insertion_block_number": [block_number],
"leaf_index": [index],
"message_id": "0x..."
}
]
}'
```
**Request schema:**
```json
{
"merkle_tree_insertions": [
{
"chain": "<domain_id as number>",
"insertion_block_number": "<block number as number>",
"leaf_index": "<leaf index as number>",
"message_id": "<0x-prefixed H256 hash>"
}
]
}
```
**Verify response:** The API should return a success response with the count of inserted entries.
### Step 4: Restart Relayer
**IMPORTANT: User confirmation required before executing.**
Use `AskUserQuestion` to confirm:
- Question: "Do you want to restart the relayer to apply the database fixes?"
- Options: "Yes, restart relayer" / "No, I'll restart manually later"
**Only proceed if the user explicitly confirms.**
Once confirmed, restart the relayer to rebuild its in-memory merkle tree:
```bash
pnpm --dir typescript/infra exec tsx ./scripts/agents/restart-agents.ts -e [environment] --context hyperlane --role relayer
```
### Step 5: Validate Fix
After the relayer restarts, verify the fix:
#### 5.1: Get Latest Index
Query Grafana for the current tree size:
```
Use mcp__grafana__query_prometheus with:
- datasourceUid: grafanacloud-prom
- expr: hyperlane_latest_tree_insertion_index{origin="[origin]", hyperlane_deployment="[environment]"}
- startTime: now-1h
- queryType: instant
```
#### 5.2: Spot-Check Roots at Key Indices
Compare validator and relayer roots at three points: first fixed index, middle, and latest.
```bash
index=[INDEX]
validator_root=$(curl -s "https://hyperlane-[environment]-[origin]-validator-0.s3.us-east-1.amazonaws.com/checkpoint_${index}_with_id.json" | jq -r '.value.checkpoint.root')
relayer_root=$(curl -s "localhost:9090/merkle_proofs?domain_id=[domain_id]&leaf_index=${index}&root_index=${index}" | jq -r '.root')
echo "Index $index:"
echo " Validator: $validator_root"
echo " Relayer: 0x$relayer_root"
if [ "$validator_root" = "0x$relayer_root" ]; then echo " ✓ Match"; else echo " ❌ MISMATCH"; fi
```
Run this for:
1. First fixed index (e.g., 37352)
2. Middle index (e.g., 39000)
3. Latest index (e.g., 41172)
#### 5.3: Verify Mismatch Metric is Clear
```
Use mcp__grafana__query_prometheus with:
- datasourceUid: grafanacloud-prom
- expr: hyperlane_merkle_root_mismatch{origin="[origin]"}
- startTime: now-1h
- queryType: instant
```
**Expected result:** Empty result or value of 0.
#### 5.4: Report Results
Present validation results in a table:
| Index | Location | Result |
| ----- | ----------- | ------- |
| 37352 | First fixed | ✓ Match |
| 39000 | Middle | ✓ Match |
| 41172 | Latest | ✓ Match |
If still mismatched:
- Inform the user that additional entries may need fixing
- Suggest re-running `/investigate-merkle-root-mismatch` to investigate further
## API Reference
### Relayer Endpoints
| Endpoint | Method | Description |
| ------------------------- | ------ | ----------------------------------- |
| `/merkle_tree_insertions` | GET | List merkle tree insertions from DB |
| `/merkle_tree_insertions` | POST | Insert/update merkle tree entries |
### Request/Response Examples
**POST /merkle_tree_insertions**
Request:
```json
{
"merkle_tree_insertions": [
{
"chain": 1101,
"insertion_block_number": 9891832,
"leaf_index": 1477,
"message_id": "0x4bb3e20db45366a6a360ad2639c5421ea622a69b89b2edb045aa97e2051529b7"
}
]
}
```
Response (success):
```json
{
"status": "success",
"data": {
"count": 1
}
}
```
## Common Issues
1. **Port-forward disconnected:** Re-establish before applying fixes
2. **API returns error:** Check the error message, verify domain_id and message_id format
3. **Relayer restart fails:** Check kubectl access and pod status
4. **Fix didn't work:** May have missed some mismatched indices, re-investigate
## Runbook Reference
Full runbook: https://www.notion.so/hyperlanexyz/Merkle-Root-Mismatch-26a6d35200d680a2857dcd0b228d4ab7
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!