1use thiserror::Error;
4
5#[derive(Debug, Error)]
7pub enum ActionError {
8 #[error("HTTP status error: {status} for {url}")]
10 HttpStatus { status: u16, url: String },
11
12 #[error("Action timed out after {ms}ms: {context}")]
14 Timeout { ms: u64, context: String },
15
16 #[error("No matching branch for switch node '{node_id}'")]
18 NoMatchingBranch { node_id: String },
19
20 #[error("Transform failed: {0}")]
22 Transform(String),
23
24 #[error("Code execution failed: {0}")]
26 CodeExecution(String),
27
28 #[error("Sandbox initialization failed: {0}")]
30 SandboxInit(String),
31
32 #[error("Missing credential: {0}")]
34 MissingCredential(String),
35
36 #[error("No database connection: {0}")]
38 NoDatabase(String),
39
40 #[error("Invalid timestamp: {0}")]
42 InvalidTimestamp(String),
43
44 #[error("Webhook wait timed out after {ms}ms")]
46 WebhookTimeout { ms: u64 },
47
48 #[error("Webhook cancelled: {0}")]
50 WebhookCancelled(String),
51
52 #[error("Condition timed out after {ms}ms")]
54 ConditionTimeout { ms: u64 },
55
56 #[error("No branch completed for merge node '{node_id}'")]
58 NoBranchCompleted { node_id: String },
59
60 #[error("Insufficient branches: got {got}, need {need}")]
62 InsufficientBranches { got: u32, need: u32 },
63
64 #[error("Email auth failed: {0}")]
66 EmailAuth(String),
67
68 #[error("Email send failed: {0}")]
70 EmailSend(String),
71
72 #[error("Notification send failed: {0}")]
74 NotificationSend(String),
75
76 #[error("RSS fetch failed: {0}")]
78 RssFetch(String),
79
80 #[error("RSS parse failed: {0}")]
82 RssParse(String),
83
84 #[error("File read failed: {0}")]
86 FileRead(String),
87
88 #[error("File write failed: {0}")]
90 FileWrite(String),
91
92 #[error("File delete failed: {0}")]
94 FileDelete(String),
95
96 #[error("File parse failed: {0}")]
98 FileParse(String),
99
100 #[error("{0}")]
102 Other(String),
103}
104
105impl From<ActionError> for adk_core::AdkError {
106 fn from(err: ActionError) -> Self {
107 use adk_core::{ErrorCategory, ErrorComponent};
108
109 let (category, code) = match &err {
110 ActionError::HttpStatus { .. } => (ErrorCategory::Internal, "action.http_status"),
111 ActionError::Timeout { .. } => (ErrorCategory::Timeout, "action.timeout"),
112 ActionError::NoMatchingBranch { .. } => {
113 (ErrorCategory::InvalidInput, "action.no_matching_branch")
114 }
115 ActionError::Transform(_) => (ErrorCategory::Internal, "action.transform"),
116 ActionError::CodeExecution(_) => (ErrorCategory::Internal, "action.code_execution"),
117 ActionError::SandboxInit(_) => (ErrorCategory::Internal, "action.sandbox_init"),
118 ActionError::MissingCredential(_) => {
119 (ErrorCategory::Unauthorized, "action.missing_credential")
120 }
121 ActionError::NoDatabase(_) => (ErrorCategory::Unavailable, "action.no_database"),
122 ActionError::InvalidTimestamp(_) => {
123 (ErrorCategory::InvalidInput, "action.invalid_timestamp")
124 }
125 ActionError::WebhookTimeout { .. } => {
126 (ErrorCategory::Timeout, "action.webhook_timeout")
127 }
128 ActionError::WebhookCancelled(_) => {
129 (ErrorCategory::Cancelled, "action.webhook_cancelled")
130 }
131 ActionError::ConditionTimeout { .. } => {
132 (ErrorCategory::Timeout, "action.condition_timeout")
133 }
134 ActionError::NoBranchCompleted { .. } => {
135 (ErrorCategory::Internal, "action.no_branch_completed")
136 }
137 ActionError::InsufficientBranches { .. } => {
138 (ErrorCategory::Internal, "action.insufficient_branches")
139 }
140 ActionError::EmailAuth(_) => (ErrorCategory::Unauthorized, "action.email_auth"),
141 ActionError::EmailSend(_) => (ErrorCategory::Internal, "action.email_send"),
142 ActionError::NotificationSend(_) => {
143 (ErrorCategory::Internal, "action.notification_send")
144 }
145 ActionError::RssFetch(_) => (ErrorCategory::Unavailable, "action.rss_fetch"),
146 ActionError::RssParse(_) => (ErrorCategory::Internal, "action.rss_parse"),
147 ActionError::FileRead(_) => (ErrorCategory::Internal, "action.file_read"),
148 ActionError::FileWrite(_) => (ErrorCategory::Internal, "action.file_write"),
149 ActionError::FileDelete(_) => (ErrorCategory::Internal, "action.file_delete"),
150 ActionError::FileParse(_) => (ErrorCategory::Internal, "action.file_parse"),
151 ActionError::Other(_) => (ErrorCategory::Internal, "action.other"),
152 };
153
154 adk_core::AdkError::new(ErrorComponent::Graph, category, code, err.to_string())
155 .with_source(err)
156 }
157}