Skip to main content

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}