1use serde::Serialize;
2use std::fmt;
3
4#[derive(Debug, Serialize)]
6#[serde(tag = "type", content = "data")]
7pub enum AtentoError {
8 Io {
10 path: String,
11 #[serde(serialize_with = "serialize_io_error")]
12 source: std::io::Error,
13 },
14
15 YamlParse {
17 context: String,
18 #[serde(serialize_with = "serialize_yaml_error")]
19 source: serde_yaml::Error,
20 },
21
22 JsonSerialize { message: String },
24
25 Validation(String),
27
28 Execution(String),
30
31 StepExecution { step: String, reason: String },
33
34 TypeConversion { expected: String, got: String },
36
37 UnresolvedReference { reference: String, context: String },
39
40 Timeout { context: String, timeout_secs: u64 },
42
43 Runner(String),
45}
46
47fn serialize_io_error<S>(
49 error: &std::io::Error,
50 serializer: S,
51) -> std::result::Result<S::Ok, S::Error>
52where
53 S: serde::Serializer,
54{
55 serializer.serialize_str(&error.to_string())
56}
57
58fn serialize_yaml_error<S>(
59 error: &serde_yaml::Error,
60 serializer: S,
61) -> std::result::Result<S::Ok, S::Error>
62where
63 S: serde::Serializer,
64{
65 serializer.serialize_str(&error.to_string())
66}
67
68impl fmt::Display for AtentoError {
71 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
72 match self {
73 Self::Io { path, source } => {
74 write!(f, "Failed to read file '{path}': {source}")
75 }
76 Self::YamlParse { context, source } => {
77 write!(f, "Failed to parse YAML in '{context}': {source}")
78 }
79 Self::JsonSerialize { message } => {
80 write!(f, "Failed to serialize results: {message}")
81 }
82 Self::Validation(msg) => {
83 write!(f, "Chain validation failed: {msg}")
84 }
85 Self::Execution(msg) => {
86 write!(f, "Chain execution failed: {msg}")
87 }
88 Self::StepExecution { step, reason } => {
89 write!(f, "Step '{step}' failed: {reason}")
90 }
91 Self::TypeConversion { expected, got } => {
92 write!(f, "Expected {expected} value, got: {got}")
93 }
94 Self::UnresolvedReference { reference, context } => {
95 write!(f, "Unresolved reference '{reference}' in {context}")
96 }
97 Self::Timeout {
98 context,
99 timeout_secs,
100 } => {
101 write!(f, "{context} timeout after {timeout_secs}s")
102 }
103 Self::Runner(msg) => {
104 write!(f, "Runner error: {msg}")
105 }
106 }
107 }
108}
109
110impl std::error::Error for AtentoError {
111 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
112 match self {
113 Self::Io { source, .. } => Some(source),
114 Self::YamlParse { source, .. } => Some(source),
115 _ => None,
117 }
118 }
119}
120
121impl From<serde_json::Error> for AtentoError {
122 fn from(err: serde_json::Error) -> Self {
123 Self::JsonSerialize {
124 message: err.to_string(),
125 }
126 }
127}
128
129pub type Result<T> = std::result::Result<T, AtentoError>;