Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions crates/client/flashblocks/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,8 @@ pub enum ProtocolError {
#[derive(Debug, Clone, Eq, PartialEq, Error)]
pub enum ProviderError {
/// Missing canonical header for a given block number.
#[error(
"missing canonical header for block {block_number}. This can be ignored if the node has recently restarted, restored from a snapshot or is still syncing."
)]
/// This typically occurs during node startup, snapshot restore, or while syncing.
#[error("missing canonical header for block {block_number}")]
MissingCanonicalHeader {
/// The block number for which the header is missing.
block_number: u64,
Expand Down Expand Up @@ -169,7 +168,7 @@ mod tests {
#[rstest]
#[case::missing_canonical_header(
ProviderError::MissingCanonicalHeader { block_number: 12345 },
"missing canonical header for block 12345. This can be ignored if the node has recently restarted, restored from a snapshot or is still syncing."
"missing canonical header for block 12345"
)]
#[case::state_provider(
ProviderError::StateProvider("connection failed".to_string()),
Expand Down
6 changes: 6 additions & 0 deletions crates/client/flashblocks/src/metrics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,12 @@ pub struct Metrics {
#[metric(describe = "Count of times flashblocks are unable to be converted to blocks")]
pub block_processing_error: Counter,

/// Count of times Flashblock processing was paused waiting for canonical chain sync.
#[metric(
describe = "Count of times Flashblock processing was paused waiting for canonical chain sync"
)]
pub canonical_sync_wait: Counter,

/// Count of times pending snapshot was cleared because canonical caught up.
#[metric(
describe = "Number of times pending snapshot was cleared because canonical caught up"
Expand Down
24 changes: 21 additions & 3 deletions crates/client/flashblocks/src/processor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ use tokio::sync::{Mutex, broadcast::Sender, mpsc::UnboundedReceiver};

use crate::{
ExecutionError, Metrics, PendingBlocks, PendingBlocksBuilder, PendingStateBuilder,
ProtocolError, ProviderError, Result,
ProtocolError, ProviderError, Result, StateProcessorError,
validation::{
CanonicalBlockReconciler, FlashblockSequenceValidator, ReconciliationStrategy,
ReorgDetector, SequenceValidationResult,
Expand Down Expand Up @@ -108,8 +108,26 @@ where
self.metrics.block_processing_duration.record(start_time.elapsed());
}
Err(e) => {
error!(message = "could not process Flashblock", error = %e);
self.metrics.block_processing_error.increment(1);
// Handle missing canonical header separately - this is expected during
// node startup, snapshot restore, or when still syncing
if let StateProcessorError::Provider(
ProviderError::MissingCanonicalHeader { block_number },
) = &e
{
// Use WARN level so operators can see this, but it won't trigger error alerts
// Include detailed context so operators understand exactly what's happening
warn!(
message = "Flashblock processing paused - waiting for canonical chain sync",
required_block = block_number,
flashblock_block = flashblock.metadata.block_number,
flashblock_index = flashblock.index,
hint = "node will resume Flashblock processing once canonical chain syncs to required height"
);
self.metrics.canonical_sync_wait.increment(1);
} else {
error!(message = "could not process Flashblock", error = %e);
self.metrics.block_processing_error.increment(1);
}
}
}
}
Expand Down