fix: align multipart completion checksum errors

Return AWS-compatible errors for CompleteMultipartUpload checksum failures without changing the global streaming checksum mapping. Compare explicit multipart checksum types symmetrically, distinguish missing composite part checksums, and preserve the CRC64NVME canonicalization pending a direct AWS probe.

Signed-off-by: Feng Ruohang <rh@vonng.com>
This commit is contained in:
Feng Ruohang
2026-08-27 08:50:45 +08:00
parent edc8be6ed1
commit 5d152416de
7 changed files with 261 additions and 32 deletions
+36
View File
@@ -22,6 +22,7 @@ import (
"errors"
"fmt"
"io"
"strings"
)
// Converts underlying storage error. Convenience function written to
@@ -653,6 +654,41 @@ func (e InvalidPart) Error() string {
e.PartNumber, e.ExpETag, e.GotETag)
}
var (
errCompleteMultipartChecksumMismatch = errors.New("complete multipart checksum mismatch")
errCompleteMultipartChecksumTypeMismatch = errors.New("complete multipart checksum type mismatch")
errMissingPartChecksum = errors.New("missing multipart part checksum")
)
// completeMultipartChecksumMismatch reports an object checksum mismatch
// detected while completing a multipart upload. It is distinct from
// hash.ChecksumMismatch because AWS maps completion failures to BadDigest,
// while streaming PutObject and UploadPart failures keep using
// XAmzContentChecksumMismatch.
func completeMultipartChecksumMismatch(algorithm string) error {
description := "The checksum you specified did not match the calculated checksum."
if algorithm != "" {
description = fmt.Sprintf("The %s checksum you specified did not match the calculated checksum.", algorithm)
}
return fmt.Errorf("%w: %s", errCompleteMultipartChecksumMismatch, description)
}
// completeMultipartChecksumTypeMismatch reports an explicit checksum type that
// differs from the type selected when the multipart upload was initiated.
func completeMultipartChecksumTypeMismatch(providedType, expectedType string) error {
description := fmt.Sprintf("The checksum type %s does not match the multipart upload checksum type %s.",
providedType, expectedType)
return fmt.Errorf("%w: %s", errCompleteMultipartChecksumTypeMismatch, description)
}
// missingPartChecksum reports a part whose checksum is absent from a
// composite CompleteMultipartUpload request.
func missingPartChecksum(algorithm string, partNumber int) error {
description := fmt.Sprintf("The upload was created using a %s checksum. The complete request must include the checksum for each part. It was missing for part %d in the request.",
strings.ToLower(algorithm), partNumber)
return fmt.Errorf("%w: %s", errMissingPartChecksum, description)
}
// PartTooSmall - error if part size is less than 5MB.
type PartTooSmall struct {
PartSize int64