diff --git a/litellm-rust/Cargo.lock b/litellm-rust/Cargo.lock index bf09b3c22cb..29b46c81cbb 100644 --- a/litellm-rust/Cargo.lock +++ b/litellm-rust/Cargo.lock @@ -1886,6 +1886,7 @@ dependencies = [ "reqwest 0.12.28", "serde_json", "sha2 0.10.9", + "thiserror 2.0.19", "tokio", ] diff --git a/litellm-rust/crates/auth-aws/Cargo.toml b/litellm-rust/crates/auth-aws/Cargo.toml index a4fdbc4f754..d998b647960 100644 --- a/litellm-rust/crates/auth-aws/Cargo.toml +++ b/litellm-rust/crates/auth-aws/Cargo.toml @@ -11,6 +11,7 @@ litellm-auth.workspace = true moka = { workspace = true, features = ["sync"] } serde_json.workspace = true sha2.workspace = true +thiserror.workspace = true aws-config = { version = "1.9.0", default-features = false, features = ["rustls", "rt-tokio"] } aws-credential-types = { version = "1.3.0", features = ["hardcoded-credentials"] } diff --git a/litellm-rust/crates/auth-aws/src/aws.rs b/litellm-rust/crates/auth-aws/src/aws.rs index 32035c572df..3b6b73bc6a9 100644 --- a/litellm-rust/crates/auth-aws/src/aws.rs +++ b/litellm-rust/crates/auth-aws/src/aws.rs @@ -15,8 +15,7 @@ use aws_sigv4::http_request::{ use aws_sigv4::sign::v4; use aws_smithy_runtime_api::client::identity::Identity; -use litellm_auth::Error; - +use super::Error; use super::constants::{ AWS_ACCESS_KEY_ID, AWS_EXTERNAL_ID, AWS_PROFILE_NAME, AWS_REGION, AWS_REGION_NAME, AWS_ROLE_ARN, AWS_ROLE_NAME, AWS_SECRET_ACCESS_KEY, AWS_SESSION_NAME, AWS_SESSION_TOKEN, diff --git a/litellm-rust/crates/auth-aws/src/error.rs b/litellm-rust/crates/auth-aws/src/error.rs new file mode 100644 index 00000000000..f80fbce456e --- /dev/null +++ b/litellm-rust/crates/auth-aws/src/error.rs @@ -0,0 +1,46 @@ +use thiserror::Error as ThisError; + +#[derive(Clone, Debug, ThisError, PartialEq, Eq)] +pub enum Error { + #[error("AWS profile credentials failed: {0}")] + AwsProfile(String), + #[error("AWS default credentials failed: {0}")] + AwsDefaultChain(String), + #[error("AWS role credentials failed: {0}")] + AwsAssumeRole(String), + #[error("AWS web identity credentials failed: {0}")] + AwsWebIdentity(String), + #[error("AWS web identity expiration was invalid: {0}")] + AwsWebIdentityExpiration(String), + #[error("AWS signing parameters failed: {0}")] + AwsSigningParameters(String), + #[error("AWS signable request failed: {0}")] + AwsSignableRequest(String), + #[error("AWS request signing failed: {0}")] + AwsSigning(String), + #[error("AWS web identity response had no credentials")] + AwsMissingWebIdentityCredentials, +} + +impl From for litellm_auth::Error { + fn from(error: Error) -> Self { + Self::ProviderAuthentication(error.to_string()) + } +} + +#[cfg(test)] +mod tests { + use super::Error; + + #[test] + fn converts_to_shared_auth_error_without_losing_context() { + let error = litellm_auth::Error::from(Error::AwsProfile("profile not found".into())); + + assert_eq!( + error, + litellm_auth::Error::ProviderAuthentication( + "AWS profile credentials failed: profile not found".into() + ) + ); + } +} diff --git a/litellm-rust/crates/auth-aws/src/lib.rs b/litellm-rust/crates/auth-aws/src/lib.rs index aaf1c713067..264592ccb2e 100644 --- a/litellm-rust/crates/auth-aws/src/lib.rs +++ b/litellm-rust/crates/auth-aws/src/lib.rs @@ -1,4 +1,6 @@ mod aws; pub mod constants; +mod error; pub use aws::*; +pub use error::Error; diff --git a/litellm-rust/crates/auth/src/error.rs b/litellm-rust/crates/auth/src/error.rs index 9189eb44676..4bbd707b16e 100644 --- a/litellm-rust/crates/auth/src/error.rs +++ b/litellm-rust/crates/auth/src/error.rs @@ -70,6 +70,8 @@ pub enum Error { AzureTokenAcquisition(String), #[error("credential acquisition failed: Vertex AI credentials: {0}")] VertexTokenAcquisition(String), + #[error("{0}")] + ProviderAuthentication(String), #[error("credential acquisition failed: {}", .0.iter().map(ToString::to_string).collect::>().join("; "))] CredentialChain(Vec), #[error("credential caller failed: credential caller returned an empty credential")] @@ -107,24 +109,6 @@ pub enum Error { "Missing OpenAI API Key - a Responses WebSocket call is being made but no key was passed via params or the OPENAI_API_KEY environment variable" )] MissingOpenAiResponsesApiKey, - #[error("AWS profile credentials failed: {0}")] - AwsProfile(String), - #[error("AWS default credentials failed: {0}")] - AwsDefaultChain(String), - #[error("AWS role credentials failed: {0}")] - AwsAssumeRole(String), - #[error("AWS web identity credentials failed: {0}")] - AwsWebIdentity(String), - #[error("AWS web identity expiration was invalid: {0}")] - AwsWebIdentityExpiration(String), - #[error("AWS signing parameters failed: {0}")] - AwsSigningParameters(String), - #[error("AWS signable request failed: {0}")] - AwsSignableRequest(String), - #[error("AWS request signing failed: {0}")] - AwsSigning(String), - #[error("AWS web identity response had no credentials")] - AwsMissingWebIdentityCredentials, #[error("invalid authentication header")] InvalidHeader, } diff --git a/litellm-rust/crates/core/src/error.rs b/litellm-rust/crates/core/src/error.rs index 359ad56c336..74291a03547 100644 --- a/litellm-rust/crates/core/src/error.rs +++ b/litellm-rust/crates/core/src/error.rs @@ -150,6 +150,12 @@ impl From for Error { } } +impl From for Error { + fn from(error: litellm_auth_aws::Error) -> Self { + Self::from(crate::AuthError::from(error)) + } +} + pub fn json_type_name(value: &serde_json::Value) -> &'static str { match value { serde_json::Value::Null => "null",