ethereum/go-ethereum · error

not at leaf

Error message

not at leaf

What it means

nodeIterator.LeafKey panics when the iterator is not positioned at a value leaf. LeafKey is only meaningful after Next() has landed on a leaf node (path terminated by hex 16 and stack top is a valueNode); calling it on an internal node or before the first Next is a misuse of the iterator API.

Source

Thrown at trie/iterator.go:222

func (it *nodeIterator) Parent() common.Hash {
	if len(it.stack) == 0 {
		return common.Hash{}
	}
	return it.stack[len(it.stack)-1].parent
}

func (it *nodeIterator) Leaf() bool {
	return hasTerm(it.path)
}

func (it *nodeIterator) LeafKey() []byte {
	if len(it.stack) > 0 {
		if _, ok := it.stack[len(it.stack)-1].node.(valueNode); ok {
			return hexToKeybytes(it.path)
		}
	}
	panic("not at leaf")
}

func (it *nodeIterator) LeafBlob() []byte {
	if len(it.stack) > 0 {
		if node, ok := it.stack[len(it.stack)-1].node.(valueNode); ok {
			return node
		}
	}
	panic("not at leaf")
}

func (it *nodeIterator) LeafProof() [][]byte {
	if len(it.stack) > 0 {
		if _, ok := it.stack[len(it.stack)-1].node.(valueNode); ok {
			hasher := newHasher(false)
			defer returnHasherToPool(hasher)
			proofs := make([][]byte, 0, len(it.stack))

View on GitHub (pinned to 6bb0588ad8)

Solutions

  1. Guard with if it.Leaf() { key := it.LeafKey() ... } before calling LeafKey.
  2. Always advance with Next(true/false) first and stop when it returns false.
  3. Read LeafKey/LeafBlob/LeafProof only within the same iteration step that reported Leaf()==true.

Example fix

// before
for it.Next(true) {
    key := it.LeafKey() // panics on non-leaf steps
}

// after
for it.Next(true) {
    if it.Leaf() {
        key := it.LeafKey()
        _ = key
    }
}
Defensive patterns

Strategy: validation

Validate before calling

for it.Next(true) {
    if !it.Leaf() {
        continue // structural node, LeafKey invalid here
    }
    key := it.LeafKey()
    _ = key
}

Prevention

When it happens

Trigger: Calling it.LeafKey() before checking it.Leaf(); calling it after Next() returned an internal (non-leaf) node; calling it after the iterator was exhausted.

Common situations: Iterating a trie and assuming every step yields a key; porting loops that used EthDatabase iteration semantics; forgetting the Next()-then-check-Leaf() contract of trie.NodeIterator.

Related errors


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