ethereum/go-ethereum · critical

node %x: %v

Error message

node %x: %v

What it means

mustDecodeNode panics when decodeNode fails to RLP-decode a trie node blob, embedding the node hash and the decode error in the message. It is used on the hot path where node bytes are trusted; a decode failure means the stored bytes for that hash are not a valid trie node — typically database corruption or wrong-network data.

Source

Thrown at trie/node.go:130

	}
	return resp + fmt.Sprintf("\n%s] ", ind)
}

func (n *shortNode) fstring(ind string) string {
	return fmt.Sprintf("{%x: %v} ", n.Key, n.Val.fstring(ind+"  "))
}
func (n hashNode) fstring(ind string) string {
	return fmt.Sprintf("<%x> ", []byte(n))
}
func (n valueNode) fstring(ind string) string {
	return fmt.Sprintf("%x ", []byte(n))
}

// mustDecodeNode is a wrapper of decodeNode and panic if any error is encountered.
func mustDecodeNode(hash, buf []byte) node {
	n, err := decodeNode(hash, buf)
	if err != nil {
		panic(fmt.Sprintf("node %x: %v", hash, err))
	}
	return n
}

// mustDecodeNodeUnsafe is a wrapper of decodeNodeUnsafe and panic if any error is
// encountered.
func mustDecodeNodeUnsafe(hash, buf []byte) node {
	n, err := decodeNodeUnsafe(hash, buf)
	if err != nil {
		panic(fmt.Sprintf("node %x: %v", hash, err))
	}
	return n
}

// decodeNode parses the RLP encoding of a trie node. It will deep-copy the passed
// byte slice for decoding, so it's safe to modify the byte slice afterwards. The-
// decode performance of this function is not optimal, but it is suitable for most
// scenarios with low performance requirements and hard to determine whether the

View on GitHub (pinned to 6bb0588ad8)

Solutions

  1. Run the node's database integrity checks and inspect the reported node hash in the logs.
  2. If corruption is confirmed, resync the chain data (or restore the datadir from a good backup/archive).
  3. Ensure all writers/readers of the database run the same (compatible) software version.
  4. Check disk health (dmesg/SMART) if corruption appears spontaneous.
Defensive patterns

Strategy: try-catch

Try / catch

defer func() {
    if r := recover(); r != nil {
        err = fmt.Errorf("trie node decode failed: %v", r) // message contains node hash
    }
}()
tr, err := trie.New(root, db)

Prevention

When it happens

Trigger: Loading a trie node from the database whose stored blob is malformed, truncated, or belongs to a different encoding scheme; opening a database written by incompatible software; disk-level corruption or partial writes.

Common situations: Crash during a database write leaving partial nodes; mixing chain data from different node versions or forks; corrupted datadir after disk failure; restoring from a bad backup; snapshot files that do not match the trie root.

Related errors


AI-assisted analysis of ethereum/go-ethereum@6bb0588ad8 (2026-08-15). Data as JSON: /api/errors/d150904a52e6ffb9. Report an issue: GitHub.