ethereum/go-ethereum · error
invalid group depth size
Error message
invalid group depth size
What it means
trie/bintrie.NewBinaryTrie panics when groupDepth is outside [1, MaxGroupDepth] (MaxGroupDepth is 8). groupDepth controls how many trie levels are grouped in each serialized node group; values below 1 or above 8 break the encoding scheme, so they are rejected as invalid configuration.
Source
Thrown at trie/bintrie/trie.go:140
// operations will report the original (unhashed) account, storage, and code
// writes to the recorder so the post-state can be exported as a GenesisAlloc.
// Pass nil to detach.
func (t *BinaryTrie) SetRecorder(r *Recorder) { t.recorder = r }
// Recorder returns the currently attached alloc recorder, or nil.
func (t *BinaryTrie) Recorder() *Recorder { return t.recorder }
// ToDot converts the binary trie to a DOT language representation. Useful for debugging.
func (t *BinaryTrie) ToDot() string {
t.store.computeHash(t.store.root)
return t.store.toDot(t.store.root, "", "")
}
// NewBinaryTrie creates a new binary trie.
// groupDepth specifies the number of levels per serialized group (1-8).
func NewBinaryTrie(root common.Hash, db database.NodeDatabase, groupDepth int) (*BinaryTrie, error) {
if groupDepth < 1 || groupDepth > MaxGroupDepth {
panic("invalid group depth size")
}
reader, err := trie.NewReader(root, common.Hash{}, db)
if err != nil {
return nil, err
}
t := &BinaryTrie{
store: newNodeStore(),
reader: reader,
tracer: trie.NewPrevalueTracer(),
groupDepth: groupDepth,
}
// Parse the root node if it's not empty
if root != types.EmptyBinaryHash && root != types.EmptyRootHash {
blob, err := t.nodeResolver(nil, root)
if err != nil {
return nil, err
}
ref, err := t.store.deserializeNodeWithHash(blob, 0, root)View on GitHub (pinned to 6bb0588ad8)
Solutions
- Pass a groupDepth in 1..8; if unsure, use the package's default/recommended value.
- Clamp or validate external input before constructing the trie.
- Reference bintrie.MaxGroupDepth in validation instead of hard-coding 8.
Example fix
// before
tr, err := bintrie.NewBinaryTrie(root, db, groupDepth) // groupDepth==0 -> panic
// after
if groupDepth < 1 || groupDepth > bintrie.MaxGroupDepth {
return nil, fmt.Errorf("groupDepth %d out of range [1, %d]", groupDepth, bintrie.MaxGroupDepth)
}
tr, err := bintrie.NewBinaryTrie(root, db, groupDepth) Defensive patterns
Strategy: validation
Validate before calling
if groupDepth < 1 || groupDepth > bintrie.MaxGroupDepth {
return nil, fmt.Errorf("groupDepth %d out of range [1, %d]", groupDepth, bintrie.MaxGroupDepth)
}
tr, err := bintrie.NewBinaryTrie(root, db, groupDepth) Prevention
- Validate groupDepth against bintrie.MaxGroupDepth instead of hard-coding the bound.
- Default missing config values to a known-good depth before construction.
- Reject zero-valued ints from config structs explicitly (Go zero value 0 is invalid here).
When it happens
Trigger: Calling bintrie.NewBinaryTrie(root, db, 0) or with depth 9+; computing depth from user input or config without bounds checking; passing an uninitialized int (0) for groupDepth.
Common situations: Config-driven tree tuning where a typo or missing default yields 0; porting code from a library version with a different valid range; using a constant defined elsewhere that drifted out of range.
Related errors
AI-assisted analysis of ethereum/go-ethereum@6bb0588ad8 (2026-08-15).
Data as JSON: /api/errors/a862c63b594e1105.
Report an issue: GitHub.