Skip to main content

a2a_rs/domain/
error.rs

1use thiserror::Error;
2
3/// Standard JSON-RPC error codes
4pub const PARSE_ERROR: i32 = -32700;
5pub const INVALID_REQUEST: i32 = -32600;
6pub const METHOD_NOT_FOUND: i32 = -32601;
7pub const INVALID_PARAMS: i32 = -32602;
8pub const INTERNAL_ERROR: i32 = -32603;
9
10/// A2A specific error codes
11pub const TASK_NOT_FOUND: i32 = -32001;
12pub const TASK_NOT_CANCELABLE: i32 = -32002;
13pub const PUSH_NOTIFICATION_NOT_SUPPORTED: i32 = -32003;
14pub const UNSUPPORTED_OPERATION: i32 = -32004;
15pub const CONTENT_TYPE_NOT_SUPPORTED: i32 = -32005;
16pub const INVALID_AGENT_RESPONSE: i32 = -32006;
17pub const AUTHENTICATED_EXTENDED_CARD_NOT_CONFIGURED: i32 = -32007;
18
19/// Custom application-specific error codes (outside spec range)
20pub const DATABASE_ERROR: i32 = -32100;
21
22/// Error type for the A2A protocol operations
23#[derive(Error, Debug)]
24pub enum A2AError {
25    #[error("JSON-RPC error: {code} - {message}")]
26    JsonRpc {
27        code: i32,
28        message: String,
29        data: Option<serde_json::Value>,
30    },
31
32    #[error("JSON parse error: {0}")]
33    JsonParse(#[from] serde_json::Error),
34
35    #[error("Invalid request: {0}")]
36    InvalidRequest(String),
37
38    #[error("Invalid parameters: {0}")]
39    InvalidParams(String),
40
41    #[error("Method not found: {0}")]
42    MethodNotFound(String),
43
44    #[error("Task not found: {0}")]
45    TaskNotFound(String),
46
47    #[error("Task not cancelable: {0}")]
48    TaskNotCancelable(String),
49
50    #[error("Push notification not supported")]
51    PushNotificationNotSupported,
52
53    #[error("Unsupported operation: {0}")]
54    UnsupportedOperation(String),
55
56    #[error("Content type not supported: {0}")]
57    ContentTypeNotSupported(String),
58
59    #[error("Invalid agent response: {0}")]
60    InvalidAgentResponse(String),
61
62    #[error("Authenticated extended card not configured")]
63    AuthenticatedExtendedCardNotConfigured,
64
65    #[error("Internal error: {0}")]
66    Internal(String),
67
68    #[error("Validation error in {field}: {message}")]
69    ValidationError { field: String, message: String },
70
71    #[error("Database error: {0}")]
72    DatabaseError(String),
73
74    #[error("IO error: {0}")]
75    Io(#[from] std::io::Error),
76}
77
78impl A2AError {
79    /// Convert an A2AError to a JSON-RPC error value
80    pub fn to_jsonrpc_error(&self) -> serde_json::Value {
81        let (code, message) = match self {
82            A2AError::JsonParse(_) => (PARSE_ERROR, "Invalid JSON payload"),
83            A2AError::InvalidRequest(_) => (INVALID_REQUEST, "Request payload validation error"),
84            A2AError::MethodNotFound(_) => (METHOD_NOT_FOUND, "Method not found"),
85            A2AError::InvalidParams(_) => (INVALID_PARAMS, "Invalid parameters"),
86            A2AError::TaskNotFound(_) => (TASK_NOT_FOUND, "Task not found"),
87            A2AError::TaskNotCancelable(_) => (TASK_NOT_CANCELABLE, "Task cannot be canceled"),
88            A2AError::PushNotificationNotSupported => (
89                PUSH_NOTIFICATION_NOT_SUPPORTED,
90                "Push Notification is not supported",
91            ),
92            A2AError::UnsupportedOperation(_) => {
93                (UNSUPPORTED_OPERATION, "This operation is not supported")
94            }
95            A2AError::ContentTypeNotSupported(_) => {
96                (CONTENT_TYPE_NOT_SUPPORTED, "Incompatible content types")
97            }
98            A2AError::InvalidAgentResponse(_) => (INVALID_AGENT_RESPONSE, "Invalid agent response"),
99            A2AError::AuthenticatedExtendedCardNotConfigured => (
100                AUTHENTICATED_EXTENDED_CARD_NOT_CONFIGURED,
101                "Authenticated Extended Card is not configured",
102            ),
103            A2AError::ValidationError { .. } => (INVALID_PARAMS, "Validation error"),
104            A2AError::DatabaseError(_) => (DATABASE_ERROR, "Database error"),
105            A2AError::Internal(_) => (INTERNAL_ERROR, "Internal error"),
106            _ => (INTERNAL_ERROR, "Internal error"),
107        };
108
109        serde_json::json!({
110            "code": code,
111            "message": message,
112            "data": null,
113        })
114    }
115}