From 796cf4afe5cbfcc3a7d301ab8bb1931b4b3bc7ee Mon Sep 17 00:00:00 2001 From: Wes Tarle Date: Mon, 16 Mar 2026 18:13:39 -0400 Subject: [PATCH] feat(gax): add getErrorInfoList to ErrorDetails --- .../com/google/api/gax/rpc/ErrorDetails.java | 32 +++++++++++++++++++ .../google/api/gax/rpc/ErrorDetailsTest.java | 22 +++++++++++++ 2 files changed, 54 insertions(+) diff --git a/gax-java/gax/src/main/java/com/google/api/gax/rpc/ErrorDetails.java b/gax-java/gax/src/main/java/com/google/api/gax/rpc/ErrorDetails.java index 45ba427b6e..b29d802b4e 100644 --- a/gax-java/gax/src/main/java/com/google/api/gax/rpc/ErrorDetails.java +++ b/gax-java/gax/src/main/java/com/google/api/gax/rpc/ErrorDetails.java @@ -44,6 +44,8 @@ import com.google.rpc.RequestInfo; import com.google.rpc.ResourceInfo; import com.google.rpc.RetryInfo; +import java.util.ArrayList; +import java.util.Collections; import java.util.List; import javax.annotation.Nullable; @@ -60,6 +62,14 @@ public ErrorInfo getErrorInfo() { return unpack(ErrorInfo.class); } + /** + * This returns all occurrences of ErrorInfo. A single error response may contain multiple + * ErrorInfo messages. + */ + public List getErrorInfoList() { + return unpackList(ErrorInfo.class); + } + /** * Describes when the clients can retry a failed request. Clients could ignore the recommendation * here or retry when this information is missing from error responses. @@ -172,4 +182,26 @@ T unpack(Class errorTypeClazz) { } return null; } + + @VisibleForTesting + List unpackList(Class errorTypeClazz) { + List rawErrorMessages = getRawErrorMessages(); + if (rawErrorMessages == null) { + return Collections.emptyList(); + } + List unpackedMessages = new ArrayList<>(); + for (Any detail : rawErrorMessages) { + if (detail.is(errorTypeClazz)) { + try { + unpackedMessages.add(detail.unpack(errorTypeClazz)); + } catch (InvalidProtocolBufferException e) { + throw new ProtocolBufferParsingException( + String.format( + "Failed to unpack %s from raw error messages", errorTypeClazz.getSimpleName()), + e); + } + } + } + return Collections.unmodifiableList(unpackedMessages); + } } diff --git a/gax-java/gax/src/test/java/com/google/api/gax/rpc/ErrorDetailsTest.java b/gax-java/gax/src/test/java/com/google/api/gax/rpc/ErrorDetailsTest.java index 90d05e5e3b..a8baf4350f 100644 --- a/gax-java/gax/src/test/java/com/google/api/gax/rpc/ErrorDetailsTest.java +++ b/gax-java/gax/src/test/java/com/google/api/gax/rpc/ErrorDetailsTest.java @@ -188,6 +188,28 @@ void errorInfo_shouldUnpackErrorInfoProtoMessage() { Truth.assertThat(errorDetails.getErrorInfo()).isEqualTo(ERROR_INFO); } + @Test + void unpackList_shouldReturnEmptyListIfRawErrorMessagesIsNull() { + errorDetails = ErrorDetails.builder().setRawErrorMessages(null).build(); + Truth.assertThat(errorDetails.unpackList(ErrorInfo.class)).isEmpty(); + } + + @Test + void getErrorInfoList_shouldUnpackAllErrorInfoProtoMessages() { + ErrorInfo errorInfo2 = + ErrorInfo.newBuilder().setDomain("googleapis.com").setReason("ANOTHER_REASON").build(); + + errorDetails = + ErrorDetails.builder() + .setRawErrorMessages( + ImmutableList.of(Any.pack(ERROR_INFO), Any.pack(DEBUG_INFO), Any.pack(errorInfo2))) + .build(); + + Truth.assertThat(errorDetails.getErrorInfoList()) + .containsExactly(ERROR_INFO, errorInfo2) + .inOrder(); + } + @Test void retryInfo_shouldUnpackRetryInfoProtoMessage() { Truth.assertThat(errorDetails.getRetryInfo()).isEqualTo(RETRY_INFO);