From 5c253e557e567e7702a46e8b23be0782394e32bf Mon Sep 17 00:00:00 2001 From: Bosul Mun Date: Wed, 1 Jul 2026 03:43:11 +0200 Subject: [PATCH] core/rawdb: prevent truncateHead from returning an error for empty tables (#35258) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- core/rawdb/freezer_table.go | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/core/rawdb/freezer_table.go b/core/rawdb/freezer_table.go index c770e89989..d18b75c2f7 100644 --- a/core/rawdb/freezer_table.go +++ b/core/rawdb/freezer_table.go @@ -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 {