Skip to main content

foundry_local_sdk/
error.rs

1use thiserror::Error;
2
3/// Stable error codes reported by the native Foundry Local library.
4#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
5#[non_exhaustive]
6pub enum NativeErrorCode {
7    Ok,
8    NotImplemented,
9    Internal,
10    InvalidArgument,
11    InvalidUsage,
12    OperationCancelled,
13    Network,
14    Unknown(i32),
15}
16
17/// Errors that can occur when using the Foundry Local SDK.
18#[derive(Debug, Error)]
19pub enum FoundryLocalError {
20    /// The native core library returned an error.
21    #[error("native error ({code:?}): {message}")]
22    Native {
23        code: NativeErrorCode,
24        message: String,
25    },
26    /// The native core library could not be loaded.
27    #[error("library load error: {reason}")]
28    LibraryLoad { reason: String },
29    /// A command executed against the native core returned an error.
30    #[error("command execution error: {reason}")]
31    CommandExecution { reason: String },
32    /// The provided configuration is invalid.
33    #[error("invalid configuration: {reason}")]
34    InvalidConfiguration { reason: String },
35    /// A model operation failed (load, unload, download, etc.).
36    #[error("model operation error: {reason}")]
37    ModelOperation { reason: String },
38    /// An HTTP request to the external service failed.
39    #[error("HTTP request error: {0}")]
40    HttpRequest(#[from] reqwest::Error),
41    /// Serialization or deserialization of JSON data failed.
42    #[error("serialization error: {0}")]
43    Serialization(#[from] serde_json::Error),
44    /// A validation check on user-supplied input failed.
45    #[error("validation error: {reason}")]
46    Validation { reason: String },
47    /// An I/O error occurred.
48    #[error("I/O error: {0}")]
49    Io(#[from] std::io::Error),
50    /// An internal SDK error (e.g. poisoned lock).
51    #[error("internal error: {reason}")]
52    Internal { reason: String },
53}
54
55impl FoundryLocalError {
56    /// Returns the native error code, if this error originated in the native library.
57    pub fn native_code(&self) -> Option<NativeErrorCode> {
58        match self {
59            Self::Native { code, .. } => Some(*code),
60            _ => None,
61        }
62    }
63
64    /// Returns the native error message, if this error originated in the native library.
65    pub fn native_message(&self) -> Option<&str> {
66        match self {
67            Self::Native { message, .. } => Some(message),
68            _ => None,
69        }
70    }
71}
72
73/// Convenience alias used throughout the SDK.
74pub type Result<T> = std::result::Result<T, FoundryLocalError>;
75
76#[cfg(test)]
77mod tests {
78    use super::{FoundryLocalError, NativeErrorCode};
79
80    #[test]
81    fn native_error_exposes_code_and_message() {
82        let error = FoundryLocalError::Native {
83            code: NativeErrorCode::Network,
84            message: "connection failed".into(),
85        };
86
87        assert_eq!(error.native_code(), Some(NativeErrorCode::Network));
88        assert_eq!(error.native_message(), Some("connection failed"));
89    }
90
91    #[test]
92    fn non_native_error_has_no_native_details() {
93        let error = FoundryLocalError::Validation {
94            reason: "invalid".into(),
95        };
96
97        assert_eq!(error.native_code(), None);
98        assert_eq!(error.native_message(), None);
99    }
100}