talon_core/expansion/error.rs
1//! Error type for the LLM expansion client.
2
3use thiserror::Error;
4
5use crate::llm::ChatError;
6
7/// Errors returned by [`ExpansionClient`].
8///
9/// JSON decode failures are treated as graceful degradation (empty result)
10/// rather than errors; only transport-level problems reach this type.
11///
12/// [`ExpansionClient`]: crate::expansion::ExpansionClient
13#[derive(Debug, Error)]
14#[non_exhaustive]
15pub enum ExpansionError {
16 /// `reqwest::Client` could not be constructed.
17 #[error("expansion client build failed: {message}")]
18 Build {
19 /// Redacted error detail.
20 message: String,
21 },
22
23 /// HTTP transport failure or non-2xx status from the sidecar.
24 #[error(
25 "expansion HTTP error{}: {message}",
26 .status.map(|s| format!(" ({s})")).unwrap_or_default()
27 )]
28 Http {
29 /// HTTP status code when a response was received, `None` for transport failures.
30 status: Option<u16>,
31 /// Redacted detail (URL or response body snippet).
32 message: String,
33 /// Whether the underlying transport failure was a timeout.
34 timed_out: bool,
35 },
36}
37
38impl From<ChatError> for ExpansionError {
39 fn from(value: ChatError) -> Self {
40 match value {
41 ChatError::Build { message } => Self::Build { message },
42 ChatError::Http {
43 status,
44 message,
45 timed_out,
46 } => Self::Http {
47 status,
48 message,
49 timed_out,
50 },
51 ChatError::MalformedResponse => Self::Http {
52 status: None,
53 message: "malformed chat response".to_string(),
54 timed_out: false,
55 },
56 }
57 }
58}