nautechsystems/nautilus_trader · error · anyhow::Error
Verified finalized header ledger is empty
Error message
Verified finalized header ledger is empty
What it means
Raised in database.rs:3730 when the execution_verification_nonce row exists for the chain/wallet but the execution_verified_finalized_header ledger contains no rows. The nonce position cannot be loaded without a finalized-header tip to anchor it, so the library treats the missing ledger as an inconsistent state rather than returning an empty position.
Source
Thrown at crates/adapters/blockchain/src/cache/database.rs:3730
anyhow::ensure!(
stored_version == manifest_version && stored_digest == manifest_digest,
"Execution verification manifest identity changed"
);
let row = sqlx::query_as::<_, (i64, String, String, i64, Option<String>, String)>(
"
SELECT number, hash, parent_hash, timestamp, base_fee_per_gas, manifest_digest
FROM execution_verified_finalized_header
WHERE chain_id = $1 AND wallet_address = $2
ORDER BY number DESC
LIMIT 1
",
)
.bind(chain_id)
.bind(wallet_address)
.fetch_optional(&self.pool)
.await
.context("failed to load verified finalized header tip")?
.ok_or_else(|| anyhow::anyhow!("Verified finalized header ledger is empty"))?;
let (number, hash, parent_hash, timestamp, base_fee, digest) = row;
anyhow::ensure!(
digest == manifest_digest,
"Finalized header manifest identity changed"
);
Ok(Some(ExecutionVerificationPosition {
next_canonical_nonce: u64::try_from(nonce).context("Canonical nonce is negative")?,
revision: u64::try_from(revision).context("Canonical nonce revision is negative")?,
finalized_tip: ExecutionVerifiedHeader {
number: u64::try_from(number).context("Finalized header number is negative")?,
hash,
parent_hash,
timestamp: u64::try_from(timestamp)
.context("Finalized header timestamp is negative")?,
base_fee_per_gas: base_fee
.map(|value| {
value
.parse::<u128>()View on GitHub (pinned to 18893faf8b)
Solutions
- Re-run verification bootstrap to rebuild the finalized-header ledger for this chain/wallet.
- Restore the ledger from backup if rows were deleted accidentally.
- Check for a cleanup/retention job that removes execution_verified_finalized_header rows and exclude the active wallet/chain.
- If bootstrapping, ensure it completes atomically (nonce row and first header committed together) before resuming verification.
Example fix
-- before: inconsistent state SELECT COUNT(*) FROM execution_verified_finalized_header WHERE chain_id=$1 AND wallet_address=$2; -- 0 -- after: re-bootstrap so the ledger holds at least one verified header SELECT COUNT(*) FROM execution_verified_finalized_header WHERE chain_id=$1 AND wallet_address=$2; -- >= 1
Defensive patterns
Strategy: validation
Validate before calling
let headers: i64 = sqlx::query_scalar(
"SELECT COUNT(*) FROM execution_verified_finalized_header \
WHERE chain_id = $1 AND wallet_address = $2",
).bind(chain_id).bind(wallet).fetch_one(&pool).await?;
if headers == 0 {
anyhow::bail!("header ledger empty; bootstrap verification first");
} Try / catch
match load_position(...).await {
Err(e) if e.to_string().contains("Verified finalized header ledger is empty") => {
// re-run bootstrap to rebuild the ledger before resuming
},
other => other?,
} Prevention
- Bootstrap nonce row and first verified header atomically
- Exclude active wallets from ledger retention/cleanup jobs
- Monitor ledger emptiness as an integrity alert
When it happens
Trigger: Calling load_execution_verification_position after the nonce row was written but before any finalized header was recorded, or after the header ledger was truncated/deleted while the nonce row survived.
Common situations: Partial/corrupted bootstrap that persisted the nonce but crashed before writing the first verified header; manual deletion of execution_verified_finalized_header rows; ledger retention/cleanup job removing all headers for the wallet.
Understand the failure class
Background: EmptyResultError / "no results found": when an API or scraper succeeds but returns zero rows — this error's family across 9 libraries.
Related errors
- Execution verification manifest identity changed
- Finalized header manifest identity changed
- Failed to lock finalized header tip: {e}
- Failed to read verified action nonce ledger: {e}
- Verified finalized header ledger is not continuous
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/82758ec4c2a05cf4.
Report an issue: GitHub.