From 62abe558aee1f2161303f2c968c042a4172e45a9 Mon Sep 17 00:00:00 2001 From: Gatefixer <312823363+lance-gatefixer[bot]@users.noreply.github.com> Date: Fri, 7 Aug 2026 14:21:49 +0000 Subject: [PATCH] fix(storage): report AWS credential failures as I/O --- .../src/object_store/providers/aws.rs | 51 +++++++++++++++++-- 1 file changed, 47 insertions(+), 4 deletions(-) diff --git a/rust/lance-io/src/object_store/providers/aws.rs b/rust/lance-io/src/object_store/providers/aws.rs index ee70b76a042..8464f228933 100644 --- a/rust/lance-io/src/object_store/providers/aws.rs +++ b/rust/lance-io/src/object_store/providers/aws.rs @@ -492,10 +492,12 @@ impl CredentialProvider for AwsCredentialAdapter { token: creds.session_token().map(|s| s.to_string()), })) } else { - let refreshed_creds = - Arc::new(self.inner.provide_credentials().await.map_err(|e| { - Error::internal(format!("Failed to get AWS credentials: {:?}", e)) - })?); + let refreshed_creds = Arc::new( + self.inner + .provide_credentials() + .await + .map_err(|e| Error::io(format!("Failed to get AWS credentials: {:?}", e)))?, + ); self.cache .write() @@ -580,6 +582,7 @@ pub type DynamicStorageOptionsCredentialProvider = mod tests { use crate::object_store::ObjectStoreRegistry; use crate::object_store::StorageOptionsProvider; + use aws_credential_types::provider::error::CredentialsError; use mock_instant::thread_local::MockClock; use object_store::path::Path; use std::sync::atomic::{AtomicBool, Ordering}; @@ -605,6 +608,46 @@ mod tests { } } + #[derive(Debug)] + struct FailingAwsCredentialsProvider; + + impl ProvideCredentials for FailingAwsCredentialsProvider { + fn provide_credentials<'a>( + &'a self, + ) -> aws_credential_types::provider::future::ProvideCredentials<'a> + where + Self: 'a, + { + aws_credential_types::provider::future::ProvideCredentials::new(async { + Err(CredentialsError::provider_error(Box::new( + std::io::Error::other("Glue credential endpoint unavailable"), + ))) + }) + } + } + + #[tokio::test] + async fn test_aws_credential_failure_is_io_error() { + let provider = AwsCredentialAdapter::new( + Arc::new(FailingAwsCredentialsProvider), + Duration::from_secs(60), + ); + + let error = provider.get_credential().await.unwrap_err(); + let object_store::Error::Generic { source, .. } = &error else { + panic!("expected a generic object store error, got {error}"); + }; + assert!(matches!( + source.downcast_ref::(), + Some(Error::IO { .. }) + )); + + let message = error.to_string(); + assert!(message.contains("Failed to get AWS credentials")); + assert!(message.contains("Glue credential endpoint unavailable")); + assert!(!message.contains("Encountered internal error")); + } + #[tokio::test] async fn test_injected_aws_creds_option_is_used() { let mock_provider = Arc::new(MockAwsCredentialsProvider::default());