entelix_memory_openai/error.rs
1//! Local error type. Surfaces to callers as `entelix_core::Error::Provider`
2//! when crossing the public `Embedder::embed` boundary — the embedder's
3//! `Result` alias `entelix_core::Result` ultimately consumes this.
4
5use thiserror::Error;
6
7use entelix_core::error::Error;
8
9/// Result alias used inside `entelix-memory-openai`.
10pub type OpenAiEmbedderResult<T> = std::result::Result<T, OpenAiEmbedderError>;
11
12/// Errors that can surface from `OpenAiEmbedder`.
13#[derive(Debug, Error)]
14#[non_exhaustive]
15pub enum OpenAiEmbedderError {
16 /// Network / HTTP failure reaching the OpenAI API. Carries the
17 /// underlying `reqwest::Error` chain.
18 #[error("network failure: {message}")]
19 Network {
20 /// Human-readable summary.
21 message: String,
22 /// Underlying transport error.
23 #[source]
24 source: Option<Box<dyn std::error::Error + Send + Sync + 'static>>,
25 },
26
27 /// Non-2xx HTTP status from OpenAI. Body is truncated to keep
28 /// log volume bounded under malicious upstream payloads.
29 #[error("HTTP {status}: {body}")]
30 HttpStatus {
31 /// HTTP status code.
32 status: u16,
33 /// Truncated response body.
34 body: String,
35 },
36
37 /// Server returned a malformed JSON body (missing `data`, vector
38 /// dimension mismatch, etc.).
39 #[error("malformed response: {0}")]
40 Malformed(String),
41
42 /// Configuration error — invalid base URL, missing credentials,
43 /// dimension mismatch at build time.
44 #[error("configuration error: {0}")]
45 Config(String),
46
47 /// Credential resolution failed.
48 #[error(transparent)]
49 Credential(Error),
50
51 /// JSON encode/decode failure.
52 #[error(transparent)]
53 Serde(#[from] serde_json::Error),
54}
55
56impl OpenAiEmbedderError {
57 /// Wrap any transport-layer error as a [`OpenAiEmbedderError::Network`].
58 pub fn network<E>(source: E) -> Self
59 where
60 E: std::error::Error + Send + Sync + 'static,
61 {
62 Self::Network {
63 message: source.to_string(),
64 source: Some(Box::new(source)),
65 }
66 }
67}
68
69impl From<OpenAiEmbedderError> for Error {
70 fn from(err: OpenAiEmbedderError) -> Self {
71 match err {
72 OpenAiEmbedderError::Config(msg) => Self::config(msg),
73 OpenAiEmbedderError::Credential(e) => e,
74 other => Self::provider_network_from(other),
75 }
76 }
77}