claude_code_sdk/
errors.rs1use thiserror::Error;
4use tracing::error;
5
6#[derive(Error, Debug)]
8pub enum ClaudeSDKError {
9 #[error("CLI connection error: {0}")]
10 CLIConnection(#[from] CLIConnectionError),
11
12 #[error("CLI not found: {0}")]
13 CLINotFound(#[from] CLINotFoundError),
14
15 #[error("Process error: {0}")]
16 Process(#[from] ProcessError),
17
18 #[error("JSON decode error: {0}")]
19 CLIJSONDecode(#[from] CLIJSONDecodeError),
20
21 #[error("IO error: {0}")]
22 Io(#[from] std::io::Error),
23
24 #[error("Other error: {0}")]
25 Other(String),
26}
27
28#[derive(Error, Debug)]
30#[error("Unable to connect to Claude Code: {message}")]
31pub struct CLIConnectionError {
32 pub message: String,
33}
34
35impl CLIConnectionError {
36 pub fn new(message: impl Into<String>) -> Self {
37 let message_str = message.into();
38 error!(message = %message_str, "CLI connection error occurred");
39 Self {
40 message: message_str,
41 }
42 }
43}
44
45#[derive(Error, Debug)]
47#[error("Claude Code not found: {message}")]
48pub struct CLINotFoundError {
49 pub message: String,
50 pub cli_path: Option<String>,
51}
52
53impl CLINotFoundError {
54 pub fn new(message: impl Into<String>) -> Self {
55 let message_str = message.into();
56 error!(message = %message_str, "Claude CLI not found");
57 Self {
58 message: message_str,
59 cli_path: None,
60 }
61 }
62
63 pub fn with_path(message: impl Into<String>, cli_path: impl Into<String>) -> Self {
64 let cli_path_string = cli_path.into();
65 let message_str = message.into();
66 error!(
67 message = %message_str,
68 cli_path = %cli_path_string,
69 "Claude CLI not found at specified path"
70 );
71 Self {
72 message: format!("{}: {}", message_str, cli_path_string),
73 cli_path: Some(cli_path_string),
74 }
75 }
76}
77
78#[derive(Error, Debug)]
80pub struct ProcessError {
81 pub message: String,
82 pub exit_code: Option<i32>,
83 pub stderr: Option<String>,
84}
85
86impl ProcessError {
87 pub fn new(message: impl Into<String>) -> Self {
88 let message_str = message.into();
89 error!(message = %message_str, "Process error occurred");
90 Self {
91 message: message_str,
92 exit_code: None,
93 stderr: None,
94 }
95 }
96
97 pub fn with_exit_code(message: impl Into<String>, exit_code: i32) -> Self {
98 let message_str = message.into();
99 error!(
100 message = %message_str,
101 exit_code = exit_code,
102 "Process error with exit code"
103 );
104 Self {
105 message: message_str,
106 exit_code: Some(exit_code),
107 stderr: None,
108 }
109 }
110
111 pub fn with_stderr(message: impl Into<String>, exit_code: Option<i32>, stderr: impl Into<String>) -> Self {
112 let message_str = message.into();
113 let stderr_str = stderr.into();
114 error!(
115 message = %message_str,
116 exit_code = exit_code,
117 stderr_preview = %stderr_str.chars().take(200).collect::<String>(),
118 "Process error with stderr output"
119 );
120 Self {
121 message: message_str,
122 exit_code,
123 stderr: Some(stderr_str),
124 }
125 }
126}
127
128impl std::fmt::Display for ProcessError {
129 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
130 write!(f, "{}", self.message)?;
131
132 if let Some(exit_code) = self.exit_code {
133 write!(f, " (exit code: {})", exit_code)?;
134 }
135
136 if let Some(stderr) = &self.stderr {
137 write!(f, "\nError output: {}", stderr)?;
138 }
139
140 Ok(())
141 }
142}
143
144#[derive(Error, Debug)]
146pub struct CLIJSONDecodeError {
147 pub line: String,
148 pub original_error: serde_json::Error,
149}
150
151impl CLIJSONDecodeError {
152 pub fn new(line: impl Into<String>, original_error: serde_json::Error) -> Self {
153 let line_str = line.into();
154 error!(
155 line_preview = %line_str.chars().take(100).collect::<String>(),
156 parse_error = %original_error,
157 "Failed to decode JSON from CLI output"
158 );
159 Self {
160 line: line_str,
161 original_error,
162 }
163 }
164}
165
166impl std::fmt::Display for CLIJSONDecodeError {
167 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
168 let line_preview = if self.line.len() > 100 {
169 format!("{}...", &self.line[..100])
170 } else {
171 self.line.clone()
172 };
173
174 write!(f, "Failed to decode JSON: {}", line_preview)
175 }
176}