Skip to content

Sync_issues

Synchronization issues are among the most common problems encountered when running blockchain nodes. A node that fails to sync properly cannot participate in the network, serve RPC requests, or validate transactions. Understanding the various sync issues, their symptoms, and solutions is essential for maintaining a healthy blockchain infrastructure. This chapter provides comprehensive troubleshooting guidance for Ethereum and other blockchain networks.


46.1 Understanding Blockchain Synchronization

Section titled “46.1 Understanding Blockchain Synchronization”
┌─────────────────────────────────────────────────────────────┐
│ BLOCKCHAIN SYNC PROCESS │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Network │───►│ Discovery │───►│ Download │ │
│ │ Peers │ │ Blocks │ │ Headers │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────┐ │
│ │ Execute │ │
│ │ State │ │
│ └─────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────┐ │
│ │ Verify │ │
│ │ Results │ │
│ └─────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────┐ │
│ │ Finalized │ │
│ │ State │ │
│ └─────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
StageDescriptionDuration
Header SyncDownload block headersMinutes to hours
Body SyncDownload block bodiesHours
State SyncDownload state trieHours to days
CatchupNear HEAD, executingMinutes

┌─────────────────────────────────────────┐
│ STUCK SYNC INDICATORS │
├─────────────────────────────────────────┤
│ │
│ ✓ Block height not progressing │
│ ✓ Peer count appears healthy │
│ ✓ No error messages in logs │
│ ✓ CPU usage normal │
│ ✓ Memory usage normal │
│ │
│ Example: │
│ Current Block: 18500000 │
│ Target Block: 18500100 │
│ (No change for 30+ minutes) │
│ │
└─────────────────────────────────────────┘
Terminal window
# Check current block
curl -X POST http://localhost:8545 \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}'
# Check sync status
curl -X POST http://localhost:8545 \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","method":"eth_syncing","params":[],"id":1}'
# Check peer count
curl -X POST http://localhost:8545 \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","method":"net_peerCount","params":[],"id":1}'
# View recent logs
journalctl -u geth --since "30 minutes ago" | tail -50
CauseDescriptionProbability
Database corruptionLevelDB/RocksDB corruptionHigh
Peer issuesConnected to stale peersMedium
Consensus issuesFork in chainLow
Resource constraintsMemory/disk pressureMedium
Network partitionIsolated from networkLow
Terminal window
# Stop the node
sudo systemctl stop geth
# Backup important data (keystore only)
cp -r /data/ethereum/keystore /backup/keystore
# Remove chaindata
rm -rf /data/ethereum/geth/chaindata
# Remove state data
rm -rf /data/ethereum/geth/triecache
# Optional: Remove snapshots if corrupted
rm -rf /data/ethereum/geth/snapshots
# Start the node
sudo systemctl start geth
# Monitor sync progress
geth attach http://localhost:8545
> eth.syncing
Terminal window
# Ethereum Mainnet Bootnodes
geth --bootnodes \
"enr:-KG4QOtcLhT1LioJW5XHmhLGr9jnoJ5XF8J8p TzW7yGrqDzoP3z6E1T5C9LwK3uK8Q6G7F9B2M1K3W8=-BMgBFYHr7tJ3z6E1T5C9LwK3uK8Q6G7F9B2M1K3W8@bootnode1.mainnet.ethdisco.net:30303,\
enr:-Ly4QFn-6sJ8tJ3z6E1T5C9LwK3uK8Q6G7F9B2M1K3W8=-BMgBFYHr7tJ3z6E1T5C9LwK3uK8Q6G7F9B2M1K3W8@bootnode2.mainnet.ethdisco.net:30303,\
enr:-Ku4QO7sJ8tJ3z6E1T5C9LwK3uK8Q6G7F9B2M1K3W8=-BMgBFYHr7tJ3z6E1T5C9LwK3uK8Q6G7F9B2M1K3W8@bootnode3.mainnet.ethdisco.net:30303"
Terminal window
# Check memory
free -h
# Check disk space
df -h
# Check disk I/O
iostat -x 5
# Check CPU
top
htop
# Check for OOM killer
dmesg | grep -i "out of memory"
Terminal window
# Use geth removedb utility
geth removedb --datadir /data/ethereum
# Or specify individual databases
geth removedb --datadir /data/ethereum --chaindata
geth removedb --datadir /data/ethereum --ancient

┌─────────────────────────────────────────┐
│ SLOW SYNC INDICATORS │
├─────────────────────────────────────────┤
│ │
│ ✓ Sync progressing but very slowly │
│ ✓ Block height increases slowly │
│ ✓ High resource usage │
│ ✓ Many peer disconnections │
│ │
│ Example Progress: │
│ Before: 100 blocks/hour │
│ After: 10 blocks/hour │
│ │
└─────────────────────────────────────────┘
Sync ModeSpeedResource Usage
Full SyncSlowestHigh
Fast SyncMediumMedium
Snap SyncFastMedium
Light SyncFastestLow
Terminal window
# Increase max peers
geth --maxpeers 100 --datadir /data/ethereum
# Check current peer count
geth attach http://localhost:8545
> net.peerCount
Terminal window
# Increase cache for 32GB+ RAM system
geth --cache 8192 --datadir /data/ethereum
# For 64GB+ system
geth --cache 16384 --datadir /data/ethereum
# Check current cache usage
geth attach http://localhost:8545
> debug.getBlockChainInfo()
Terminal window
# Use NVMe instead of SATA SSD
# Check current storage type
lsblk -o NAME,TYPE,SIZE,MODEL
# Benchmark storage
fio --name=seqread --readonly --filename=/tmp/fiotest --ioengine=libaio --iodepth=1 --bs=4M --direct=1 --size=1G --numjobs=1 --runtime=60 --time_based
# Recommended: Samsung 990 Pro, WD Black SN850X
Terminal window
# Use snap sync (default in recent Geth versions)
geth --syncmode snap --datadir /data/ethereum
# Verify sync mode
geth attach http://localhost:8545
> eth.syncing

Terminal window
# 1. Check if actually syncing
curl -X POST http://localhost:8545 \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","method":"eth_syncing","params":[],"id":1}'
# Response should show:
# - currentBlock
# - highestBlock
# - knownStates
# - pulledStates
# If not syncing, response is "false"
# 2. Check network connectivity
curl -X POST http://localhost:8545 \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","method":"net_listening","params":[],"id":1}'
# 3. Check peers
curl -X POST http://localhost:8545 \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","method":"admin_peers","params":[],"id":1}'
Terminal window
# Test internet connectivity
ping -c 4 8.8.8.8
ping -c 4 google.com
# Test specific ports
nc -zv bootnode.mainnet.ethdisco.net 30303
# Check firewall
sudo ufw status
sudo iptables -L -n
Terminal window
# View recent errors
journalctl -u geth --since "1 hour ago" | grep -i "error"
# Check for specific issues
journalctl -u geth | grep -i "no peers"
journalctl -u geth | grep -i "connection refused"
journalctl -u geth | grep -i "timeout"
Terminal window
# Stop node
sudo systemctl stop geth
# Backup state (optional)
cp -r /data/ethereum/geth/chaindata /backup/chaindata-backup
# Remove state
rm -rf /data/ethereum/geth/chaindata
rm -rf /data/ethereum/geth/triecache
# Restart with new peers
sudo systemctl start geth

Terminal window
# Check if you're on a fork
# Compare your block with external block explorers
# Get your current block
curl -X POST http://localhost:8545 \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}'
# Compare with:
# - https://etherscan.io/blocks
# - https://blockchain.info/
# Check for reorgs
geth attach http://localhost:8545
> debug.traceBlockByNumber(eth.blockNumber)
Terminal window
# 1. Check which fork you're on
geth attach http://localhost:8545
> eth.getBlock(eth.blockNumber).hash
# 2. Compare with canonical chain
# Etherscan API
curl "https://api.etherscan.io/api?module=block&action=getblocknobytime&timestamp=$(date +%s)&closest=before"
# 3. If on wrong fork, resync
sudo systemctl stop geth
rm -rf /data/ethereum/geth/chaindata
sudo systemctl start geth

After The Merge, syncing became more complex:

┌─────────────────────────────────────────────────────────────┐
│ POST-MERGE SYNC CHALLENGES │
├─────────────────────────────────────────────────────────────┤
│ │
│ Execution Layer (EL) ◄──► Consensus Layer (CL) │
│ │
│ Issues: │
│ ✓ CL node must be running for EL to sync │
│ ✓ EL needs authenticated connection to CL │
│ ✓ Different sync modes for EL vs CL │
│ ✓ Beacon chain data required │
│ │
└─────────────────────────────────────────────────────────────┘
Terminal window
# 1. Ensure both EL and CL are running
systemctl status geth
systemctl status lighthouse
systemctl status prysm
systemctl status teku
# 2. Check EL/CL connection
geth attach http://localhost:8545
> debug.getExecutionEnginePayload()
# 3. Check JWT secret
cat /data/ethereum/geth/jwtsecret
# Should match CL configuration
# 4. If using Lighthouse:
lighthouse --execution-endpoint http://localhost:8551 \
--execution-jwt /data/ethereum/geth/jwtsecret
# 5. Check for sync progress
curl -X GET http://localhost:5052/eth/v1/node/syncing

Terminal window
# Erigon requires specific flags
erigon \
--datadir /data/ethereum \
--chain mainnet \
--http \
--http.addr 0.0.0.0 \
--http.port 8545 \
--http.api eth,net,debug,trace,txpool \
--ws
# Check Erigon sync status
curl -X POST http://localhost:8545 \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","method":"eth_syncing","params":[],"id":1}'
# Erigon flags for sync issues
# --prune.mode=minimal # Keep all history
# --prune.mode=archive # Full archive
# --externalcl # Use external consensus client

Terminal window
# Check Lighthouse sync status
curl -X GET http://localhost:5052/eth/v1/node/syncing | jq
# Check block proposed
curl -X GET http://localhost:5052/eth/v1/beacon/headers | jq
# Check validator duties
curl -X GET http://localhost:5052/eth/v1/validator/duties/proposer/1200 | jq
# Check if beacon chain synced
curl -X GET http://localhost:5052/eth/v1/node/health | jq
Terminal window
# 1. Check if beacon chain is synced
lighthouse bn --testnet=mainnet status
# 2. Check EL connection
curl -X POST http://localhost:8551 \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $(cat /data/ethereum/geth/jwtsecret)" \
-d '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}'
# 3. Reset beacon chain data
lighthouse bn --testnet=mainnet db clear
# 4. Restart
systemctl restart lighthouse

Terminal window
# Testnet Sync (Sepolia)
geth --sepolia \
--syncmode snap \
--bootnodes "enr:-KG4QO..."
# Testnet Sync (Goerli - deprecated)
geth --goerli \
--syncmode snap
# Mainnet Sync
geth --mainnet \
--syncmode snap
Terminal window
# Check genesis file matches network
cat /data/ethereum/geth/genesis.json | jq '.config'
# Verify network ID
curl -X POST http://localhost:8545 \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","method":"net_version","params":[],"id":1}'
# Check if bootnodes are correct
geth --bootnodes "enr:..." --network-id 12345

prometheus/alerting_rules.yml
groups:
- name: sync_alerts
rules:
- alert: NodeNotSyncing
expr: ethereum_block_height{job="geth"} == 0
for: 5m
labels:
severity: critical
annotations:
summary: "Node {{ $labels.instance }} is not syncing"
- alert: SyncStalled
expr: rate(ethereum_block_height[5m]) == 0
for: 15m
labels:
severity: warning
annotations:
summary: "Node {{ $labels.instance }} sync stalled"
- alert: SyncTooSlow
expr: rate(ethereum_block_height[5m]) < 10
for: 30m
labels:
severity: warning
annotations:
summary: "Node {{ $labels.instance }} sync too slow"
- alert: NodeBehindNetwork
expr: (ethereum_network_block - ethereum_block_height) > 100
for: 10m
labels:
severity: warning
annotations:
summary: "Node {{ $labels.instance }} is behind network by 100+ blocks"
check_sync.sh
#!/bin/bash
RPC_URL="http://localhost:8545"
MAX_BLOCK_DIFF=10
# Get current block
CURRENT=$(curl -s -X POST $RPC_URL \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' \
| jq -r '.result' | printf "%d\n" "0x$(cat)")
# Get network block (from block explorers)
NETWORK_BLOCK=$(curl -s "https://api.etherscan.io/api?module=block&action=getblocknobytime&timestamp=$(date +%s)&closest=before" \
| jq -r '.result[0].blockNumber')
DIFF=$((NETWORK_BLOCK - CURRENT))
if [ $DIFF -gt $MAX_BLOCK_DIFF ]; then
echo "WARNING: Node is $DIFF blocks behind network"
exit 1
else
echo "OK: Node is synced (diff: $DIFF)"
exit 0
fi

IssueSolution
Stuck at block Xrm -rf /data/ethereum/geth/chaindata && systemctl restart geth
No peersAdd bootnodes, check firewall
Slow syncIncrease peers, use snap sync, upgrade hardware
Database corruptiongeth removedb then resync
Fork issuesCompare with Etherscan, resync if needed
Post-Merge issuesEnsure CL node running, check JWT
Terminal window
# Nuclear option - delete everything except keys
systemctl stop geth
rm -rf /data/ethereum/geth/*
cp -r /backup/keystore /data/ethereum/keystore
systemctl start geth

  • Stuck sync is often solved by fresh sync or database reset
  • Slow sync requires hardware upgrades or configuration tuning
  • No progress is usually network or resource related
  • Post-Merge requires both EL and CL to be synced
  • Monitoring is critical for early problem detection
  • Prevention: Regular health checks, adequate resources, updated software

In Chapter 47: Memory & CPU Optimization, we’ll explore performance optimization techniques.


Last Updated: 2026-02-22