nautechsystems/nautilus_trader · error · anyhow::Error
Failed to get block info for chain {}: {}
Error message
Failed to get block info for chain {}: {} What it means
This error is raised when the query fetching the chain's cached block info (e.g. latest block number/timestamp used as the sync watermark) fails or the sqlx fetch_one errors. Note fetch_one also errors when zero rows are returned, so an unseeded/empty chain state also produces this message.
Source
Thrown at crates/adapters/blockchain/src/cache/database.rs:430
/// Returns an error if the database query fails.
pub async fn get_block_consistency_status(
&self,
chain: &Chain,
) -> anyhow::Result<CachedBlocksConsistencyStatus> {
log::debug!("Fetching block consistency status");
let result: (i64, i64) = sqlx::query_as(
"
SELECT
COALESCE((SELECT number FROM block WHERE chain_id = $1 ORDER BY number DESC LIMIT 1), 0) as max_block,
get_last_continuous_block($1) as last_continuous_block
"
)
.bind(chain.chain_id as i32)
.fetch_one(&self.pool)
.await
.map_err(|e| {
anyhow::anyhow!(
"Failed to get block info for chain {}: {}",
chain.chain_id,
e
)
})?;
Ok(CachedBlocksConsistencyStatus::new(
result.0 as u64,
result.1 as u64,
))
}
/// Inserts or updates a block record in the database.
///
/// # Errors
///
/// Returns an error if the database operation fails.
pub async fn add_block(&self, chain_id: u32, block: &Block) -> anyhow::Result<()> {View on GitHub (pinned to 18893faf8b)
Solutions
- Check the {e} source: QueryReturnedNoRows means the chain has no cached block info yet — seed or sync the chain first
- Verify migrations/partitions exist for this chain_id
- Confirm connection settings and that the correct database is targeted
- Handle the empty case explicitly in the caller if starting from scratch is expected
Example fix
// before: treats empty cache as hard failure
let info = db.get_block_info(&chain).await?;
// after: fall back to a starting block when nothing is cached
let info = match db.get_block_info(&chain).await {
Ok(info) => info,
Err(e) if is_empty_result(&e) => BlockInfo::default_start(chain),
Err(e) => return Err(e.into()),
}; Defensive patterns
Strategy: fallback
Validate before calling
// check the chain has cached state before reading block info
let has_row: (i64,) = sqlx::query_as(
"SELECT COUNT(*) FROM block WHERE chain_id = $1"
).bind(chain.chain_id as i32).fetch_one(&pool).await?;
let cache_populated = has_row.0 > 0; Try / catch
let start = match db.get_block_info(&chain).await {
Ok(info) => info.next_block(),
Err(e) if is_query_returned_no_rows(&e) => chain.start_block(), // fresh cache
Err(e) => return Err(e.into()),
}; Prevention
- Seed the chain row and run an initial sync before querying cached block info
- Distinguish empty-cache (QueryReturnedNoRows) from real query errors via the error source
- Confirm the correct DATABASE_URL / environment when seeing this on startup
- Handle first-run against a fresh database as a normal, expected path
When it happens
Trigger: Calling the get-block-info method for a chain when the row is missing (chain never synced) or the SELECT fails (connection, permissions, missing table/partition).
Common situations: Pointing the adapter at a fresh database where the chain has no cached blocks; wrong DATABASE_URL/environment; sqlx row-type mismatch after a schema change.
Understand the failure class
Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they mean and how to fix them — this error's family across 28 libraries.
Related errors
- Failed to seed chain table: {e}
- Failed to call create_block_partition for chain {}: {e}
- Failed to call create_token_partition for chain {}: {e}
- Failed to insert into block table: {e}
- Failed to batch insert into block table: {e}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/7b6c68d3ba979fe5.
Report an issue: GitHub.