kimi_wire/error.rs
1use std::time::Duration;
2
3/// Errors that can occur when interacting with the Kimi Wire protocol.
4///
5/// ADR: `std::io::Error` and `serde_json::Error` are flattened to `String`
6/// variants (`Io(String)`, `JsonParse(String)`) rather than preserved with
7/// `#[source]`. This is a deliberate trade-off: `WireError` implements
8/// `Clone + PartialEq`, which is required for test ergonomics (comparing
9/// expected vs actual errors, injecting errors into mock clients). Dynamic
10/// error types (`Box<dyn std::error::Error>`) are neither `Clone` nor
11/// `PartialEq`, and `#[source]` would make the enum non-cloneable. Callers
12/// still receive the full error message; the cause chain is simply collapsed
13/// into the display string at the boundary.
14#[derive(thiserror::Error, Debug, Clone, PartialEq)]
15#[non_exhaustive]
16pub enum WireError {
17 /// The wire stream closed unexpectedly.
18 #[error("wire stream closed")]
19 StreamClosed,
20
21 /// A read or write operation timed out.
22 #[error("wire I/O timed out after {0:?}")]
23 Timeout(Duration),
24
25 /// Failed to spawn the Kimi CLI process.
26 #[error("failed to spawn process: {0}")]
27 SpawnFailed(String),
28
29 /// Failed to parse a JSON message.
30 #[error("JSON parse error: {0}")]
31 JsonParse(String),
32
33 /// Failed to serialize a value to JSON.
34 #[error("JSON serialization error: {0}")]
35 JsonSerialize(String),
36
37 /// The server returned a JSON-RPC error response.
38 /// The server returned a JSON-RPC error response.
39 #[error("wire request failed: {message} (code: {code})")]
40 RequestFailed {
41 /// JSON-RPC error code.
42 code: i32,
43 /// Error message from the server.
44 message: String,
45 },
46
47 /// Received a response with an unexpected request id.
48 /// Received a response with an unexpected request id.
49 #[error("unexpected response id: expected {expected}, got {got}")]
50 UnexpectedResponseId {
51 /// Expected request id.
52 expected: String,
53 /// Actual request id received.
54 got: String,
55 },
56
57 /// The server does not support the requested method.
58 #[error("method not found: {0}")]
59 MethodNotFound(String),
60
61 /// An unknown wire message type was received.
62 #[error("unknown wire message type: {0}")]
63 UnknownMessageType(String),
64
65 /// The payload was not a JSON object.
66 #[error("wire message payload must be a JSON object")]
67 InvalidPayloadType,
68
69 /// An I/O error occurred.
70 #[error("I/O error: {0}")]
71 Io(String),
72
73 /// A generic internal error.
74 #[error("internal error: {0}")]
75 Internal(String),
76}
77
78impl From<std::io::Error> for WireError {
79 fn from(err: std::io::Error) -> Self {
80 WireError::Io(err.to_string())
81 }
82}
83
84impl From<serde_json::Error> for WireError {
85 fn from(err: serde_json::Error) -> Self {
86 if err.is_io() {
87 WireError::Io(err.to_string())
88 } else {
89 WireError::JsonParse(err.to_string())
90 }
91 }
92}