This is an automated email from the ASF dual-hosted git repository.

jtuglu1 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/druid.git


The following commit(s) were added to refs/heads/master by this push:
     new d06aa83cd80 fix: retry transient AWS credential resolution failures 
(#19558)
d06aa83cd80 is described below

commit d06aa83cd809f6cedec15ba8f8e8e12de26e1587
Author: jtuglu1 <[email protected]>
AuthorDate: Fri Jun 5 15:18:41 2026 -0700

    fix: retry transient AWS credential resolution failures (#19558)
    
    S3 segment pushes that use the AWS SDK v2 transfer manager can resolve 
credentials on the async upload path. If a file-session credential refresh, 
container credential lookup, or IMDS lookup is temporarily unavailable, the SDK 
reports an SdkClientException such as 'Unable to load credentials from any of 
the providers in the chain'.
    
    Druid's S3 push path already wraps uploads in retryS3Operation, but these 
credential-provider failures were not classified as recoverable after the SDK 
v2 migration. That made an intermittent credential miss fail the task 
immediately instead of using the existing retry budget.
---
 .../org/apache/druid/common/aws/AWSClientUtil.java | 14 +++++++++--
 .../apache/druid/common/aws/AWSClientUtilTest.java | 27 ++++++++++++++++++++++
 .../org/apache/druid/storage/s3/S3UtilsTest.java   | 26 +++++++++++++++++++++
 3 files changed, 65 insertions(+), 2 deletions(-)

diff --git 
a/cloud/aws-common/src/main/java/org/apache/druid/common/aws/AWSClientUtil.java 
b/cloud/aws-common/src/main/java/org/apache/druid/common/aws/AWSClientUtil.java
index 68fa9e25ca4..4f138e3a750 100644
--- 
a/cloud/aws-common/src/main/java/org/apache/druid/common/aws/AWSClientUtil.java
+++ 
b/cloud/aws-common/src/main/java/org/apache/druid/common/aws/AWSClientUtil.java
@@ -62,6 +62,12 @@ public class AWSClientUtil
       "Throttling"
   );
 
+  private static final String UNABLE_TO_LOAD_CREDENTIALS_FROM_PROVIDER_CHAIN =
+      "Unable to load credentials from any of the providers in the chain";
+  private static final String FAILED_TO_LOAD_CREDENTIALS_FROM_IMDS = "Failed 
to load credentials from IMDS";
+  private static final String CANNOT_REFRESH_AWS_CREDENTIALS = "cannot refresh 
AWS credentials";
+  private static final String CANNOT_FETCH_CREDENTIALS_FROM_CONTAINER = 
"Cannot fetch credentials from container";
+
   /**
    * Checks whether an exception can be retried or not for AWS SDK v2.
    */
@@ -101,11 +107,15 @@ public class AWSClientUtil
 
     // Check for SdkClientException specific messages
     if (exception instanceof SdkClientException) {
-      String message = exception.getMessage();
+      final String message = exception.getMessage();
       if (message != null) {
         if (message.contains("Unable to execute HTTP request") ||
             message.contains("Data read has a different length than the 
expected") ||
-            message.contains("Unable to find a region")) {
+            message.contains("Unable to find a region") ||
+            message.contains(UNABLE_TO_LOAD_CREDENTIALS_FROM_PROVIDER_CHAIN) ||
+            message.contains(FAILED_TO_LOAD_CREDENTIALS_FROM_IMDS) ||
+            message.contains(CANNOT_REFRESH_AWS_CREDENTIALS) ||
+            message.contains(CANNOT_FETCH_CREDENTIALS_FROM_CONTAINER)) {
           return true;
         }
       }
diff --git 
a/cloud/aws-common/src/test/java/org/apache/druid/common/aws/AWSClientUtilTest.java
 
b/cloud/aws-common/src/test/java/org/apache/druid/common/aws/AWSClientUtilTest.java
index 6f47e78471c..535bfcc8b39 100644
--- 
a/cloud/aws-common/src/test/java/org/apache/druid/common/aws/AWSClientUtilTest.java
+++ 
b/cloud/aws-common/src/test/java/org/apache/druid/common/aws/AWSClientUtilTest.java
@@ -89,6 +89,33 @@ public class AWSClientUtilTest
     Assert.assertTrue(AWSClientUtil.isClientExceptionRecoverable(ex));
   }
 
+  @Test
+  public void testRecoverableException_CredentialsProviderChain()
+  {
+    final SdkClientException ex = SdkClientException.builder()
+        .message("Unable to load credentials from any of the providers in the 
chain AwsCredentialsProviderChain")
+        .build();
+    Assert.assertTrue(AWSClientUtil.isClientExceptionRecoverable(ex));
+  }
+
+  @Test
+  public void testRecoverableException_FileSessionCredentialsRefresh()
+  {
+    final SdkClientException ex = SdkClientException.builder()
+        .message("LazyFileSessionCredentialsProvider(): cannot refresh AWS 
credentials")
+        .build();
+    Assert.assertTrue(AWSClientUtil.isClientExceptionRecoverable(ex));
+  }
+
+  @Test
+  public void testRecoverableException_InstanceProfileCredentials()
+  {
+    final SdkClientException ex = SdkClientException.builder()
+        .message("InstanceProfileCredentialsProvider(): Failed to load 
credentials from IMDS.")
+        .build();
+    Assert.assertTrue(AWSClientUtil.isClientExceptionRecoverable(ex));
+  }
+
   @Test
   public void testRecoverableException_ClockSkewedError()
   {
diff --git 
a/extensions-core/s3-extensions/src/test/java/org/apache/druid/storage/s3/S3UtilsTest.java
 
b/extensions-core/s3-extensions/src/test/java/org/apache/druid/storage/s3/S3UtilsTest.java
index 16b8c20d0f2..dcf7b3f8d0d 100644
--- 
a/extensions-core/s3-extensions/src/test/java/org/apache/druid/storage/s3/S3UtilsTest.java
+++ 
b/extensions-core/s3-extensions/src/test/java/org/apache/druid/storage/s3/S3UtilsTest.java
@@ -36,6 +36,7 @@ import software.amazon.awssdk.services.s3.model.S3Exception;
 
 import java.io.IOException;
 import java.util.List;
+import java.util.concurrent.CompletionException;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.stream.Collectors;
 
@@ -151,6 +152,31 @@ public class S3UtilsTest
     Assert.assertEquals(maxRetries, count.get());
   }
 
+  @Test
+  public void testRetryWithAsyncCredentialProviderChainException() throws 
Exception
+  {
+    final int maxRetries = 3;
+    final AtomicInteger count = new AtomicInteger();
+    S3Utils.retryS3Operation(
+        () -> {
+          if (count.incrementAndGet() >= maxRetries) {
+            return "hey";
+          } else {
+            throw new CompletionException(
+                SdkClientException.builder()
+                                  .message(
+                                      "Unable to load credentials from any of 
the providers in the chain "
+                                      + "AwsCredentialsProviderChain"
+                                  )
+                                  .build()
+            );
+          }
+        },
+        maxRetries
+    );
+    Assert.assertEquals(maxRetries, count.get());
+  }
+
   @Test
   public void testRetryWithS3InternalError() throws Exception
   {


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to