Chain
height stays at 0
height stays at 0
Validators aren’t reaching quorum. Check that all 4 nodes are reachable from each
other:Common causes:
- One node crashed on boot (genesis mismatch)
- Network partition between containers
- BLS key rotation without re-registering
genesis hash mismatch on restart
genesis hash mismatch on restart
Sled keeps state across restarts. If genesis.json changed, wipe the DB:All contracts must be redeployed after this.
Transactions
tx stuck as 'pending'
tx stuck as 'pending'
Possible causes:
- Nonce gap —
eth_getTransactionCountahead of any submitted tx. Submit the missing nonces. - Insufficient balance — the tx was evicted from the mempool. Check
eth_getBalance. - Frontend polling stale — the tx is already confirmed but the client is still
polling an old block window. Use
eth_getTransactionReceiptdirectly.
'invalid signature' on eth_sendRawTransaction
'invalid signature' on eth_sendRawTransaction
Make sure you’re signing for chain ID
7717. MetaMask / ethers / viem auto-pick
this from the RPC, but custom signing paths often forget.'insufficient funds for gas'
'insufficient funds for gas'
Testnet gas is 1 gwei. Even so, large calls can need tens of thousands of gas. Use
eth_estimateGas before sending.relayer logs 'nonce mismatch: expected N, got M' and engagement stops committing
relayer logs 'nonce mismatch: expected N, got M' and engagement stops committing
Two nonce semantics matter here and they are easy to confuse:
eth_getTransactionCount(address, tag)onyc-nodeignores the block tag and always returns the committed state nonce. There is no pending view — asking for"pending"gives you"latest".yc_sendTransactionassigns the nonce server-side from the node’s pending-aware mempool counter (highest pending + 1), so the client cannot choose it. If pending entries stop being mined, that counter runs away from the committed nonce and the executor rejects each block’s worth of them withnonce mismatch: expected N, got M.
yscan/indexer/src/nonce.ts) that reads the committed nonce from the node, keeps a
small bounded window of unconfirmed transactions, and on a nonce rejection logs a single
[nonce] resync ... expected=N got=M WARN, drops the future-nonce backlog, and retries
with capped exponential backoff. It self-heals without restarting the container; a
restart is no longer the remedy.If a submission keeps failing it surfaces as NonceResyncExhaustedError, and if the
window stays full because the chain is not advancing it surfaces as
NonceWindowSaturatedError — both are errors returned to the caller, never an
unbounded resubmission loop.Tunable per deployment: NONCE_MAX_IN_FLIGHT (8), NONCE_MAX_ATTEMPTS (5),
NONCE_BASE_BACKOFF_MS (100), NONCE_MAX_BACKOFF_MS (4000),
NONCE_STALE_AFTER_MS (60000).Mobile API
429 Too Many Requests
429 Too Many Requests
Global rate limit is 300 req/min per IP, writes are 30/min. Back off per the
Retry-After header. Batch reads where possible.App can't reach HTTP URL
App can't reach HTTP URL
iOS and Android block cleartext HTTP by default. See the
mobile app guide for the Info.plist / network_security_config
exceptions.
Operator cheat sheet
Who to ping
- Protocol / node issues → Eduardo (
edudev825@gmail.com) - QA / mobile integration → Mostafa