Skip to main content

adk_graph/
error.rs

1//! Error types for adk-graph
2
3use crate::interrupt::Interrupt;
4use thiserror::Error;
5
6/// Result type for graph operations
7pub type Result<T> = std::result::Result<T, GraphError>;
8
9/// Errors that can occur during graph operations
10#[derive(Error, Debug)]
11pub enum GraphError {
12    /// Graph structure is invalid
13    #[error("Invalid graph structure: {0}")]
14    InvalidGraph(String),
15
16    /// Node not found
17    #[error("Node not found: {0}")]
18    NodeNotFound(String),
19
20    /// Edge target not found
21    #[error("Edge target not found: {0}")]
22    EdgeTargetNotFound(String),
23
24    /// No entry point defined
25    #[error("No entry point defined (missing edge from START)")]
26    NoEntryPoint,
27
28    /// Recursion limit exceeded
29    #[error("Recursion limit exceeded: {0} steps")]
30    RecursionLimitExceeded(usize),
31
32    /// Execution was interrupted
33    #[error("Execution interrupted: {0:?}")]
34    Interrupted(Box<InterruptedExecution>),
35
36    /// Node execution failed
37    #[error("Node '{node}' execution failed: {message}")]
38    NodeExecutionFailed { node: String, message: String },
39
40    /// State serialization error
41    #[error("State serialization error: {0}")]
42    SerializationError(String),
43
44    /// Checkpoint error
45    #[error("Checkpoint error: {0}")]
46    CheckpointError(String),
47
48    /// Router returned unknown target
49    #[error("Router returned unknown target: {0}")]
50    UnknownRouteTarget(String),
51
52    /// IO error
53    #[error("IO error: {0}")]
54    IoError(#[from] std::io::Error),
55
56    /// JSON error
57    #[error("JSON error: {0}")]
58    JsonError(#[from] serde_json::Error),
59
60    /// Database error (when sqlite feature enabled)
61    #[cfg(feature = "sqlite")]
62    #[error("Database error: {0}")]
63    DatabaseError(#[from] sqlx::Error),
64}
65
66/// Information about an interrupted execution
67#[derive(Debug, Clone)]
68pub struct InterruptedExecution {
69    /// Thread ID for resumption
70    pub thread_id: String,
71    /// Checkpoint ID for resumption
72    pub checkpoint_id: String,
73    /// The interrupt that occurred
74    pub interrupt: Interrupt,
75    /// Current state at interruption
76    pub state: crate::state::State,
77    /// Step number when interrupted
78    pub step: usize,
79}
80
81impl InterruptedExecution {
82    /// Create a new interrupted execution
83    pub fn new(
84        thread_id: String,
85        checkpoint_id: String,
86        interrupt: Interrupt,
87        state: crate::state::State,
88        step: usize,
89    ) -> Self {
90        Self { thread_id, checkpoint_id, interrupt, state, step }
91    }
92}
93
94impl From<GraphError> for adk_core::AdkError {
95    fn from(err: GraphError) -> Self {
96        use adk_core::{ErrorCategory, ErrorComponent};
97        let (category, code) = match &err {
98            GraphError::InvalidGraph(_) => (ErrorCategory::InvalidInput, "graph.invalid"),
99            GraphError::NodeNotFound(_) => (ErrorCategory::NotFound, "graph.node_not_found"),
100            GraphError::EdgeTargetNotFound(_) => {
101                (ErrorCategory::NotFound, "graph.edge_target_not_found")
102            }
103            GraphError::NoEntryPoint => (ErrorCategory::InvalidInput, "graph.no_entry_point"),
104            GraphError::RecursionLimitExceeded(_) => {
105                (ErrorCategory::Internal, "graph.recursion_limit")
106            }
107            GraphError::Interrupted(_) => (ErrorCategory::Cancelled, "graph.interrupted"),
108            GraphError::NodeExecutionFailed { .. } => {
109                (ErrorCategory::Internal, "graph.node_execution_failed")
110            }
111            GraphError::SerializationError(_) => (ErrorCategory::Internal, "graph.serialization"),
112            GraphError::CheckpointError(_) => (ErrorCategory::Internal, "graph.checkpoint"),
113            GraphError::UnknownRouteTarget(_) => {
114                (ErrorCategory::NotFound, "graph.unknown_route_target")
115            }
116            GraphError::IoError(_) => (ErrorCategory::Internal, "graph.io"),
117            GraphError::JsonError(_) => (ErrorCategory::Internal, "graph.json"),
118            #[cfg(feature = "sqlite")]
119            GraphError::DatabaseError(_) => (ErrorCategory::Internal, "graph.database"),
120        };
121        adk_core::AdkError::new(ErrorComponent::Graph, category, code, err.to_string())
122            .with_source(err)
123    }
124}