diff --git a/generator/.DevConfigs/1f197260-2f36-43db-8312-41be9543531c.json b/generator/.DevConfigs/1f197260-2f36-43db-8312-41be9543531c.json
new file mode 100644
index 000000000000..dc96b326aef7
--- /dev/null
+++ b/generator/.DevConfigs/1f197260-2f36-43db-8312-41be9543531c.json
@@ -0,0 +1,11 @@
+{
+ "services": [
+ {
+ "serviceName": "S3",
+ "type": "patch",
+ "changeLogMessages": [
+ "Fixed DeleteObjects to throw DeleteObjectsException instead of AmazonS3Exception for consistent error handling"
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/sdk/src/Services/S3/Custom/Model/Internal/MarshallTransformations/DeleteObjectsResponseUnmarshaller.cs b/sdk/src/Services/S3/Custom/Model/Internal/MarshallTransformations/DeleteObjectsResponseUnmarshaller.cs
index 0e03bfc1162e..c36b38171390 100644
--- a/sdk/src/Services/S3/Custom/Model/Internal/MarshallTransformations/DeleteObjectsResponseUnmarshaller.cs
+++ b/sdk/src/Services/S3/Custom/Model/Internal/MarshallTransformations/DeleteObjectsResponseUnmarshaller.cs
@@ -13,7 +13,9 @@
* permissions and limitations under the License.
*/
using System;
+using System.IO;
using System.Net;
+using System.Xml;
using System.Collections.Generic;
using Amazon.S3.Model;
using Amazon.S3.Util;
@@ -96,6 +98,77 @@ private static void UnmarshallResult(XmlUnmarshallerContext context,DeleteObject
return;
}
+ ///
+ /// Unmarshaller error response to exception.
+ /// For DeleteObjects operations, we always return DeleteObjectsException instead of AmazonS3Exception
+ /// to maintain consistency in exception types regardless of the specific error scenario.
+ ///
+ ///
+ ///
+ ///
+ ///
+ public override AmazonServiceException UnmarshallException(XmlUnmarshallerContext context, Exception innerException, HttpStatusCode statusCode)
+ {
+ var responseBodyBytes = context.GetResponseBodyBytes();
+
+ // First, try to parse as a standard DeleteObjects response (for cases where S3 returns mixed results)
+ if (responseBodyBytes != null && responseBodyBytes.Length > 0)
+ {
+ using (var streamCopy = new MemoryStream(responseBodyBytes))
+ using (var contextCopy = new XmlUnmarshallerContext(streamCopy, false, null))
+ {
+ try
+ {
+ var deleteResponse = this.Unmarshall(contextCopy) as DeleteObjectsResponse;
+
+ // If we successfully parsed a DeleteObjects response, use it directly
+ if (deleteResponse != null)
+ {
+ return new DeleteObjectsException(deleteResponse);
+ }
+ }
+ catch (XmlException)
+ {
+ // Response is not a valid DeleteObjects XML, fall through to error handling
+ }
+ catch (InvalidOperationException)
+ {
+ // Response is not a valid DeleteObjects XML, fall through to error handling
+ }
+ }
+ }
+
+ // For standard S3 error responses (like KeyTooLongError), create a DeleteObjectsException
+ // with the error information wrapped in a DeleteObjectsResponse
+ var errorResponse = S3ErrorResponseUnmarshaller.Instance.Unmarshall(context);
+
+ // Create a DeleteObjectsResponse containing the error information
+ var deleteObjectsResponse = new DeleteObjectsResponse();
+ deleteObjectsResponse.DeleteErrors = new List
+ {
+ new DeleteError
+ {
+ Code = errorResponse?.Code ?? "UnknownError",
+ Message = errorResponse?.Message ?? "An error occurred during the delete operation",
+ Key = "" // We don't know which specific key caused the error in batch validation scenarios
+ }
+ };
+
+ // Create the DeleteObjectsException with our constructed response
+ var deleteException = new DeleteObjectsException(deleteObjectsResponse);
+
+ // Set additional properties from the error response
+ if (errorResponse != null)
+ {
+ deleteException.ErrorCode = errorResponse.Code;
+ deleteException.RequestId = errorResponse.RequestId;
+ deleteException.StatusCode = statusCode;
+ // Note: ResponseBody will be set by the base exception handling if available
+ }
+
+ return deleteException;
+ }
+
private static DeleteObjectsResponseUnmarshaller _instance;
///