Debugging Failed Messages
Debug failed or stuck CCIP messages using a three-step workflow: track the message status, diagnose the error, and manually execute with corrected parameters.
Workflow
| Step | Command | Purpose |
|---|---|---|
| 1. Track | ccip-cli show | Check message status and identify failures |
| 2. Diagnose | ccip-cli parse | Decode error data |
| 3. Execute | ccip-cli manualExec | Retry with corrected parameters |
Prerequisites
Configure RPC endpoints for both source and destination chains:
RPC_SEPOLIA=https://ethereum-sepolia-rpc.publicnode.com
RPC_ARB_SEPOLIA=https://arbitrum-sepolia-rpc.publicnode.com
USER_KEY=0xYourPrivateKeyHere
Step 1: Track the Message
Check message status with the transaction hash from the source chain:
ccip-cli show 0xYourTransactionHash
Output Interpretation
The output contains three sections: Request, Commit, and Receipts.
- Success
- Pending
- Failed
═══ Request ═══
Source: ethereum-testnet-sepolia
Destination: ethereum-testnet-sepolia-arbitrum-1
Message ID: 0xabc123...
Sender: 0x1234...
Receiver: 0x5678...
═══ Commit ═══
Commit Tx: 0xdef456...
Block: 12345678
═══ Receipts ═══
State: SUCCESS
Exec Tx: 0xghi789...
Gas Used: 150000
No action required.
═══ Request ═══
Source: ethereum-testnet-sepolia
Destination: ethereum-testnet-sepolia-arbitrum-1
Message ID: 0xabc123...
═══ Commit ═══
Status: COMMITTED
═══ Receipts ═══
State: UNTOUCHED
Wait for execution, or proceed to Step 3 for manual execution.
═══ Request ═══
Source: ethereum-testnet-sepolia
Destination: ethereum-testnet-sepolia-arbitrum-1
Message ID: 0xabc123...
═══ Commit ═══
Status: COMMITTED
═══ Receipts ═══
State: FAILURE
Return Data: 0x08c379a0000000000000000000000000...
Decode the error (Step 2) and retry (Step 3).
Message States
| State | Description | Action |
|---|---|---|
UNTOUCHED | Committed, not executed | Wait or manual execute |
IN_PROGRESS | Execution in progress | Wait |
SUCCESS | Executed | None |
FAILURE | Execution failed | Diagnose and retry |
Step 2: Diagnose the Failure
Decode the error data from the Receipts section:
ccip-cli parse 0x08c379a0000000000000000000000000...
Common Errors
- Out of Gas
- Unsupported Token
- Receiver Revert
- Ordering
Error output:
Panic: 0x11 (Arithmetic overflow/underflow)
Or execution fails with empty return data.
Cause: Receiver contract exceeded gas limit.
Fix: Increase gas limit in manual execution:
ccip-cli manualExec 0xTxHash --gas-limit 500000 --wallet ledger
Error output:
Error: EVM2EVMOnRamp_1.2.0.UnsupportedToken(address)
Args: { token: '0x779877A7B0D9E8603169DdbD7836e478b4624789' }
Cause: Token not registered on this lane.
Fix:
- Verify token registration with
getSupportedTokens - Check token pool liquidity
- Use a supported token
Error output:
Error: "Custom error from receiver contract"
Cause: Application-specific receiver logic failed.
Fix:
- Review receiver contract logic
- Verify data format
- Check receiver permissions and state
Symptom: Message stuck as UNTOUCHED after commit.
Cause: CCIP enforces sender nonce ordering. An earlier message from the same sender failed.
Fix: Execute messages in order:
ccip-cli manualExec 0xFirstFailedTxHash \
--sender-queue \
--exec-failed \
--wallet ledger
Step 3: Manual Execution
Execute the message manually after identifying and addressing the failure cause.
Basic execution
ccip-cli manualExec 0xYourTxHash --wallet ledger
With increased gas limit
ccip-cli manualExec 0xYourTxHash \
--gas-limit 500000 \
--wallet ledger
With auto-estimated gas
Estimate gas and add a percentage margin:
ccip-cli manualExec 0xYourTxHash \
--estimate-gas-limit 20 \
--wallet ledger
Execute sender queue
Process all pending messages from a sender in order:
ccip-cli manualExec 0xFirstTxHash \
--sender-queue \
--exec-failed \
--wallet ledger
Chain-Specific Behavior
- EVM
- Solana
Gas:
- Default gas limit (~200k) may be insufficient for complex receivers
- Use
--estimate-gas-limitfor automatic estimation - Token transfers require additional gas for pool operations
Finality:
- Execution requires commit finalization
- Finality times vary by chain
Transaction size limits:
For large messages, use buffer and lookup table options:
ccip-cli manualExec 0xTxHash \
--force-buffer \
--force-lookup-table \
--wallet ledger
Compute units:
Use --compute-units instead of --gas-limit:
ccip-cli manualExec 0xTxHash \
--compute-units 500000 \
--wallet ledger
Cleanup after failed attempts:
ccip-cli manualExec 0xTxHash \
--clear-leftover-accounts \
--wallet ledger
Example
# Check message status
ccip-cli show 0xafd36a0b99d5457e403c918194cb69cd070d991dcbadc99576acfce5020c0b6b
# Output shows State: FAILURE with Return Data: 0x08c379a0000000...
# Decode the error
ccip-cli parse 0x08c379a0000000...
# Output: Error: "Insufficient gas for receiver"
# Retry with higher gas limit
ccip-cli manualExec 0xafd36a0b99d5457e403c918194cb69cd070d991dcbadc99576acfce5020c0b6b \
--gas-limit 500000 \
--wallet ledger
# Verify execution
ccip-cli show 0xafd36a0b99d5457e403c918194cb69cd070d991dcbadc99576acfce5020c0b6b
# State: SUCCESS
Common Issues
| Issue | Solution |
|---|---|
No RPC configured for chain X | Add RPC endpoint via --rpcs or .env |
Message not found | Verify transaction hash and source chain RPC |
Message not committed yet | Wait for DON to commit |
Already executed | Message succeeded; no action needed |
Wallet not configured | Set USER_KEY in .env or use --wallet |
Related
- show - Command reference
- parse - Command reference
- manualExec - Command reference
- Configuration - RPC and wallet setup