kona_engine/task_queue/tasks/build/
error.rs

1//! Contains error types for the [crate::SynchronizeTask].
2
3use crate::{
4    EngineTaskError, InsertTaskError, SynchronizeTaskError,
5    task_queue::tasks::task::EngineTaskErrorSeverity,
6};
7use alloy_rpc_types_engine::PayloadStatusEnum;
8use alloy_transport::{RpcError, TransportErrorKind};
9use kona_protocol::FromBlockError;
10use op_alloy_rpc_types_engine::OpExecutionPayloadEnvelope;
11use thiserror::Error;
12use tokio::sync::mpsc;
13
14/// An error that occurs during payload building within the engine.
15///
16/// This error type is specific to the block building process and represents failures
17/// that can occur during the automatic forkchoice update phase of [`BuildTask`].
18/// Unlike [`BuildTaskError`], which handles higher-level build orchestration errors,
19/// `EngineBuildError` focuses on low-level engine API communication failures.
20///
21/// ## Error Categories
22///
23/// - **State Validation**: Errors related to inconsistent chain state
24/// - **Engine Communication**: RPC failures during forkchoice updates
25/// - **Payload Validation**: Invalid payload status responses from the execution layer
26///
27/// [`BuildTask`]: crate::BuildTask
28#[derive(Debug, Error)]
29pub enum EngineBuildError {
30    /// The finalized head is ahead of the unsafe head.
31    #[error("Finalized head is ahead of unsafe head")]
32    FinalizedAheadOfUnsafe(u64, u64),
33    /// The forkchoice update call to the engine api failed.
34    #[error("Failed to build payload attributes in the engine. Forkchoice RPC error: {0}")]
35    AttributesInsertionFailed(#[from] RpcError<TransportErrorKind>),
36    /// The inserted payload is invalid.
37    #[error("The inserted payload is invalid: {0}")]
38    InvalidPayload(String),
39    /// The inserted payload status is unexpected.
40    #[error("The inserted payload status is unexpected: {0}")]
41    UnexpectedPayloadStatus(PayloadStatusEnum),
42    /// The payload ID is missing.
43    #[error("The inserted payload ID is missing")]
44    MissingPayloadId,
45    /// The engine is syncing.
46    #[error("The engine is syncing")]
47    EngineSyncing,
48}
49
50/// An error that occurs when running the [crate::SynchronizeTask].
51#[derive(Debug, Error)]
52pub enum BuildTaskError {
53    /// An error occurred when building the payload attributes in the engine.
54    #[error("An error occurred when building the payload attributes to the engine.")]
55    EngineBuildError(EngineBuildError),
56    /// The initial forkchoice update call to the engine api failed.
57    #[error(transparent)]
58    ForkchoiceUpdateFailed(#[from] SynchronizeTaskError),
59    /// Impossible to insert the payload into the engine.
60    #[error(transparent)]
61    PayloadInsertionFailed(#[from] InsertTaskError),
62    /// The get payload call to the engine api failed.
63    #[error(transparent)]
64    GetPayloadFailed(RpcError<TransportErrorKind>),
65    /// A deposit-only payload failed to import.
66    #[error("Deposit-only payload failed to import")]
67    DepositOnlyPayloadFailed,
68    /// Failed to re-atttempt payload import with deposit-only payload.
69    #[error("Failed to re-attempt payload import with deposit-only payload")]
70    DepositOnlyPayloadReattemptFailed,
71    /// The payload is invalid, and the derivation pipeline must
72    /// be flushed post-holocene.
73    #[error("Invalid payload, must flush post-holocene")]
74    HoloceneInvalidFlush,
75    /// Failed to convert a [`OpExecutionPayload`] to a [`L2BlockInfo`].
76    ///
77    /// [`OpExecutionPayload`]: op_alloy_rpc_types_engine::OpExecutionPayload
78    /// [`L2BlockInfo`]: kona_protocol::L2BlockInfo
79    #[error(transparent)]
80    FromBlock(#[from] FromBlockError),
81    /// Error sending the built payload envelope.
82    #[error(transparent)]
83    MpscSend(#[from] mpsc::error::SendError<OpExecutionPayloadEnvelope>),
84}
85
86impl EngineTaskError for BuildTaskError {
87    fn severity(&self) -> EngineTaskErrorSeverity {
88        match self {
89            Self::ForkchoiceUpdateFailed(inner) => inner.severity(),
90            Self::PayloadInsertionFailed(inner) => inner.severity(),
91            Self::EngineBuildError(EngineBuildError::FinalizedAheadOfUnsafe(_, _)) => {
92                EngineTaskErrorSeverity::Critical
93            }
94            Self::EngineBuildError(EngineBuildError::AttributesInsertionFailed(_)) => {
95                EngineTaskErrorSeverity::Temporary
96            }
97            Self::EngineBuildError(EngineBuildError::InvalidPayload(_)) => {
98                EngineTaskErrorSeverity::Temporary
99            }
100            Self::EngineBuildError(EngineBuildError::UnexpectedPayloadStatus(_)) => {
101                EngineTaskErrorSeverity::Temporary
102            }
103            Self::EngineBuildError(EngineBuildError::MissingPayloadId) => {
104                EngineTaskErrorSeverity::Temporary
105            }
106            Self::EngineBuildError(EngineBuildError::EngineSyncing) => {
107                EngineTaskErrorSeverity::Temporary
108            }
109            Self::GetPayloadFailed(_) => EngineTaskErrorSeverity::Temporary,
110            Self::HoloceneInvalidFlush => EngineTaskErrorSeverity::Flush,
111            Self::DepositOnlyPayloadReattemptFailed => EngineTaskErrorSeverity::Critical,
112            Self::DepositOnlyPayloadFailed => EngineTaskErrorSeverity::Critical,
113            Self::FromBlock(_) => EngineTaskErrorSeverity::Critical,
114            Self::MpscSend(_) => EngineTaskErrorSeverity::Critical,
115        }
116    }
117}