Skip to main content

rust_langgraph/
errors.rs

1//! Error types for LangGraph operations.
2//!
3//! This module defines the error types used throughout the library, providing
4//! detailed context for various failure modes in graph execution, checkpointing,
5//! and state management.
6
7
8/// The main error type for LangGraph operations.
9#[derive(Debug, thiserror::Error)]
10pub enum Error {
11    /// Error during graph execution
12    #[error("Execution error: {0}")]
13    ExecutionError(String),
14
15    /// Error during state operations
16    #[error("State error: {0}")]
17    StateError(String),
18
19    /// Error during checkpoint operations
20    #[error("Checkpoint error: {0}")]
21    CheckpointError(String),
22
23    /// Error during channel operations
24    #[error("Channel error: {0}")]
25    ChannelError(String),
26
27    /// Graph recursion limit exceeded
28    #[error("Graph recursion limit exceeded: {current} > {limit}")]
29    RecursionLimitError { current: usize, limit: usize },
30
31    /// Node not found in graph
32    #[error("Node not found: {0}")]
33    NodeNotFound(String),
34
35    /// Invalid graph configuration
36    #[error("Invalid graph configuration: {0}")]
37    InvalidGraph(String),
38
39    /// Serialization/deserialization error
40    #[error("Serialization error: {0}")]
41    SerializationError(#[from] serde_json::Error),
42
43    /// Interrupt was triggered
44    #[error("Interrupt: {0}")]
45    Interrupt(String),
46
47    /// Invalid update to state
48    #[error("Invalid update: {0}")]
49    InvalidUpdate(String),
50
51    /// Database error (when using SQL checkpointers)
52    #[cfg(any(feature = "sqlite", feature = "postgres"))]
53    #[error("Database error: {0}")]
54    DatabaseError(#[from] sqlx::Error),
55
56    /// HTTP error (when using LLM providers)
57    #[cfg(any(feature = "openai", feature = "anthropic", feature = "ollama"))]
58    #[error("HTTP error: {0}")]
59    HttpError(#[from] reqwest::Error),
60
61    /// Generic error with context
62    #[error("{0}")]
63    Other(String),
64}
65
66impl Error {
67    /// Create a new execution error
68    pub fn execution(msg: impl Into<String>) -> Self {
69        Error::ExecutionError(msg.into())
70    }
71
72    /// Create a new state error
73    pub fn state(msg: impl Into<String>) -> Self {
74        Error::StateError(msg.into())
75    }
76
77    /// Create a new checkpoint error
78    pub fn checkpoint(msg: impl Into<String>) -> Self {
79        Error::CheckpointError(msg.into())
80    }
81
82    /// Create a new channel error
83    pub fn channel(msg: impl Into<String>) -> Self {
84        Error::ChannelError(msg.into())
85    }
86
87    /// Create a new invalid graph error
88    pub fn invalid_graph(msg: impl Into<String>) -> Self {
89        Error::InvalidGraph(msg.into())
90    }
91
92    /// Create a new node not found error
93    pub fn node_not_found(name: impl Into<String>) -> Self {
94        Error::NodeNotFound(name.into())
95    }
96
97    /// Create an interrupt error
98    pub fn interrupt(msg: impl Into<String>) -> Self {
99        Error::Interrupt(msg.into())
100    }
101
102    /// Create an invalid update error
103    pub fn invalid_update(msg: impl Into<String>) -> Self {
104        Error::InvalidUpdate(msg.into())
105    }
106}
107
108/// A specialized Result type for LangGraph operations.
109pub 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}