1#[derive(Debug, thiserror::Error)]
10pub enum Error {
11 #[error("Execution error: {0}")]
13 ExecutionError(String),
14
15 #[error("State error: {0}")]
17 StateError(String),
18
19 #[error("Checkpoint error: {0}")]
21 CheckpointError(String),
22
23 #[error("Channel error: {0}")]
25 ChannelError(String),
26
27 #[error("Graph recursion limit exceeded: {current} > {limit}")]
29 RecursionLimitError { current: usize, limit: usize },
30
31 #[error("Node not found: {0}")]
33 NodeNotFound(String),
34
35 #[error("Invalid graph configuration: {0}")]
37 InvalidGraph(String),
38
39 #[error("Serialization error: {0}")]
41 SerializationError(#[from] serde_json::Error),
42
43 #[error("Interrupt: {0}")]
45 Interrupt(String),
46
47 #[error("Invalid update: {0}")]
49 InvalidUpdate(String),
50
51 #[cfg(any(feature = "sqlite", feature = "postgres"))]
53 #[error("Database error: {0}")]
54 DatabaseError(#[from] sqlx::Error),
55
56 #[cfg(any(feature = "openai", feature = "anthropic", feature = "ollama"))]
58 #[error("HTTP error: {0}")]
59 HttpError(#[from] reqwest::Error),
60
61 #[error("{0}")]
63 Other(String),
64}
65
66impl Error {
67 pub fn execution(msg: impl Into<String>) -> Self {
69 Error::ExecutionError(msg.into())
70 }
71
72 pub fn state(msg: impl Into<String>) -> Self {
74 Error::StateError(msg.into())
75 }
76
77 pub fn checkpoint(msg: impl Into<String>) -> Self {
79 Error::CheckpointError(msg.into())
80 }
81
82 pub fn channel(msg: impl Into<String>) -> Self {
84 Error::ChannelError(msg.into())
85 }
86
87 pub fn invalid_graph(msg: impl Into<String>) -> Self {
89 Error::InvalidGraph(msg.into())
90 }
91
92 pub fn node_not_found(name: impl Into<String>) -> Self {
94 Error::NodeNotFound(name.into())
95 }
96
97 pub fn interrupt(msg: impl Into<String>) -> Self {
99 Error::Interrupt(msg.into())
100 }
101
102 pub fn invalid_update(msg: impl Into<String>) -> Self {
104 Error::InvalidUpdate(msg.into())
105 }
106}
107
108pub type Result<T> = std::result::Result<T, Error>;
110
111#[cfg(test)]
112mod tests {
113 use super::*;
114
115 #[test]
116 fn test_error_creation() {
117 let err = Error::execution("test");
118 assert!(matches!(err, Error::ExecutionError(_)));
119 assert_eq!(err.to_string(), "Execution error: test");
120 }
121
122 #[test]
123 fn test_recursion_limit_error() {
124 let err = Error::RecursionLimitError {
125 current: 100,
126 limit: 50,
127 };
128 assert!(err.to_string().contains("100"));
129 assert!(err.to_string().contains("50"));
130 }
131
132 #[test]
133 fn test_error_from_json() {
134 let json_err = serde_json::from_str::<i32>("not a number").unwrap_err();
135 let err: Error = json_err.into();
136 assert!(matches!(err, Error::SerializationError(_)));
137 }
138}