Skip to main content

ethrex_p2p/snap/
error.rs

1//! Unified error types for the snap sync protocol
2//!
3//! This module consolidates all snap-related errors into a unified `SnapError` type
4//! for consistent error handling across server and client operations.
5
6use crate::rlpx::error::PeerConnectionError;
7use ethrex_rlp::error::RLPDecodeError;
8use ethrex_storage::error::StoreError;
9use ethrex_trie::TrieError;
10use spawned_concurrency::ActorError;
11use std::io::ErrorKind;
12use std::path::PathBuf;
13use thiserror::Error;
14
15/// Unified error type for snap sync protocol operations
16#[derive(Debug, Error)]
17pub enum SnapError {
18    /// Storage layer errors
19    #[error(transparent)]
20    Store(#[from] StoreError),
21
22    /// Protocol/connection errors
23    #[error(transparent)]
24    Protocol(#[from] PeerConnectionError),
25
26    /// Trie operation errors
27    #[error(transparent)]
28    Trie(#[from] TrieError),
29
30    /// RLP decoding errors
31    #[error(transparent)]
32    RlpDecode(#[from] RLPDecodeError),
33
34    /// Peer table errors
35    #[error(transparent)]
36    PeerTable(#[from] ActorError),
37
38    /// Bad request from peer (invalid or malformed request)
39    #[error("Bad request: {0}")]
40    BadRequest(String),
41
42    /// Response validation failed (invalid proof, hash mismatch, etc.)
43    #[error("Response validation failed: {0}")]
44    ValidationError(String),
45
46    /// Peer selection failed (no suitable peers available)
47    #[error("Peer selection failed: {0}")]
48    PeerSelection(String),
49
50    /// Task queue is empty when it shouldn't be
51    #[error("No tasks in queue")]
52    NoTasks,
53
54    /// Missing account data
55    #[error("No account hashes available")]
56    NoAccountHashes,
57
58    /// Missing storage data
59    #[error("No account storages available")]
60    NoAccountStorages,
61
62    /// Missing storage roots
63    #[error("No storage roots available")]
64    NoStorageRoots,
65
66    /// Unexpected internal error (indicates a bug)
67    #[error("Unexpected internal error: {0}")]
68    InternalError(String),
69
70    /// File system operation failed
71    #[error("File system error: {operation} at {}: {kind:?}", path.display())]
72    FileSystem {
73        operation: &'static str,
74        path: PathBuf,
75        kind: ErrorKind,
76    },
77
78    /// Snapshot directory operations
79    #[error("Snapshot directory error: {0}")]
80    SnapshotDir(String),
81
82    /// Task was spawned but panicked
83    #[error("Task panicked: {0}")]
84    TaskPanic(String),
85
86    /// Invalid data received from peer
87    #[error("Invalid data received")]
88    InvalidData,
89
90    /// Hash mismatch in received data
91    #[error("Hash mismatch in received data")]
92    InvalidHash,
93}
94
95impl SnapError {
96    /// Creates a file system error for directory not existing
97    pub fn dir_not_exists(path: PathBuf) -> Self {
98        Self::FileSystem {
99            operation: "check exists",
100            path,
101            kind: ErrorKind::NotFound,
102        }
103    }
104
105    /// Creates a file system error for directory creation failure
106    pub fn dir_create_failed(path: PathBuf) -> Self {
107        Self::FileSystem {
108            operation: "create directory",
109            path,
110            kind: ErrorKind::Other,
111        }
112    }
113
114    /// Creates a file system error for write failure
115    pub fn write_failed(path: PathBuf, kind: ErrorKind) -> Self {
116        Self::FileSystem {
117            operation: "write",
118            path,
119            kind,
120        }
121    }
122}
123
124/// Converts a tokio task JoinError into SnapError
125impl From<tokio::task::JoinError> for SnapError {
126    fn from(err: tokio::task::JoinError) -> Self {
127        SnapError::TaskPanic(err.to_string())
128    }
129}
130
131/// Error that occurs when dumping snapshots to disk
132#[derive(Debug, thiserror::Error)]
133#[error("Failed to dump snapshot to {}: {:?}", path.display(), error)]
134pub struct DumpError {
135    pub path: PathBuf,
136    pub error: ErrorKind,
137}
138
139impl From<DumpError> for SnapError {
140    fn from(err: DumpError) -> Self {
141        SnapError::FileSystem {
142            operation: "dump snapshot",
143            path: err.path,
144            kind: err.error,
145        }
146    }
147}