core/rawdb: prevent truncateHead from returning an error for empty tables (#35258)

This PR is related to the recent bug reported in #35210.

While trying to reproduce the error, I found that when the head state is
missing (e.g. unclean shutdown), we attempt to truncate the head to the
most recent block with state across all chain freezer tables.

However, for newly added tables such as the bal table, both the head and
tail are initialized to the minimum head of the existing chain freezer
tables. As a result, the `truncateHead` fails with the “truncate below
tail” error.

This PR fixes the issue by resetting newly added empty tables with
`items` as the tail when `truncateHead(items)` is called on them.
This commit is contained in:
Bosul Mun 2026-07-01 03:43:11 +02:00 committed by GitHub
parent 409aaefac1
commit 5c253e557e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -611,9 +611,18 @@ func (t *freezerTable) truncateHead(items uint64) error {
if existing <= items {
return nil
}
if items < t.itemHidden.Load() {
hidden := t.itemHidden.Load()
if items < hidden {
if existing == hidden {
// Empty table means that it is newly added. Its tail would be
// at the head, so we have to align the table down to the new head.
return t.resetTo(items)
}
return errors.New("truncation below tail")
}
// We need to truncate, save the old size for metrics tracking
oldSize, err := t.sizeNolock()
if err != nil {