a2a_protocol_server/
error.rs1use std::fmt;
11
12use a2a_protocol_types::error::{A2aError, ErrorCode};
13use a2a_protocol_types::task::TaskId;
14
15#[derive(Debug)]
21#[non_exhaustive]
22pub enum ServerError {
23 TaskNotFound(TaskId),
25 TaskNotCancelable(TaskId),
27 InvalidParams(String),
29 Serialization(serde_json::Error),
31 Http(hyper::Error),
33 HttpClient(String),
35 Transport(String),
37 PushNotSupported,
39 Internal(String),
41 MethodNotFound(String),
43 Protocol(A2aError),
45 PayloadTooLarge(String),
47 InvalidStateTransition {
49 task_id: TaskId,
51 from: a2a_protocol_types::task::TaskState,
53 to: a2a_protocol_types::task::TaskState,
55 },
56}
57
58impl fmt::Display for ServerError {
59 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
60 match self {
61 Self::TaskNotFound(id) => write!(f, "task not found: {id}"),
62 Self::TaskNotCancelable(id) => write!(f, "task not cancelable: {id}"),
63 Self::InvalidParams(msg) => write!(f, "invalid params: {msg}"),
64 Self::Serialization(e) => write!(f, "serialization error: {e}"),
65 Self::Http(e) => write!(f, "HTTP error: {e}"),
66 Self::HttpClient(msg) => write!(f, "HTTP client error: {msg}"),
67 Self::Transport(msg) => write!(f, "transport error: {msg}"),
68 Self::PushNotSupported => f.write_str("push notifications not supported"),
69 Self::Internal(msg) => write!(f, "internal error: {msg}"),
70 Self::MethodNotFound(m) => write!(f, "method not found: {m}"),
71 Self::Protocol(e) => write!(f, "protocol error: {e}"),
72 Self::PayloadTooLarge(msg) => write!(f, "payload too large: {msg}"),
73 Self::InvalidStateTransition { task_id, from, to } => {
74 write!(
75 f,
76 "invalid state transition for task {task_id}: {from} → {to}"
77 )
78 }
79 }
80 }
81}
82
83impl std::error::Error for ServerError {
84 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
85 match self {
86 Self::Serialization(e) => Some(e),
87 Self::Http(e) => Some(e),
88 Self::Protocol(e) => Some(e),
89 _ => None,
90 }
91 }
92}
93
94impl ServerError {
95 #[must_use]
109 pub fn to_a2a_error(&self) -> A2aError {
110 match self {
111 Self::TaskNotFound(id) => A2aError::task_not_found(id),
112 Self::TaskNotCancelable(id) => A2aError::task_not_cancelable(id),
113 Self::InvalidParams(msg) => A2aError::invalid_params(msg.clone()),
114 Self::Serialization(e) => A2aError::parse_error(e.to_string()),
115 Self::MethodNotFound(m) => {
116 A2aError::new(ErrorCode::MethodNotFound, format!("Method not found: {m}"))
117 }
118 Self::PushNotSupported => A2aError::new(
119 ErrorCode::PushNotificationNotSupported,
120 "Push notifications not supported",
121 ),
122 Self::Protocol(e) => e.clone(),
123 Self::Http(e) => A2aError::internal(e.to_string()),
124 Self::HttpClient(msg)
125 | Self::Transport(msg)
126 | Self::Internal(msg)
127 | Self::PayloadTooLarge(msg) => A2aError::internal(msg.clone()),
128 Self::InvalidStateTransition { task_id, from, to } => A2aError::invalid_params(
129 format!("invalid state transition for task {task_id}: {from} → {to}"),
130 ),
131 }
132 }
133}
134
135impl From<A2aError> for ServerError {
138 fn from(e: A2aError) -> Self {
139 Self::Protocol(e)
140 }
141}
142
143impl From<serde_json::Error> for ServerError {
144 fn from(e: serde_json::Error) -> Self {
145 Self::Serialization(e)
146 }
147}
148
149impl From<hyper::Error> for ServerError {
150 fn from(e: hyper::Error) -> Self {
151 Self::Http(e)
152 }
153}
154
155pub type ServerResult<T> = Result<T, ServerError>;