diff --git a/br/pkg/storage/ks3.go b/br/pkg/storage/ks3.go index 24aaa88e81b0d..1d422ad8683dd 100644 --- a/br/pkg/storage/ks3.go +++ b/br/pkg/storage/ks3.go @@ -512,8 +512,14 @@ func (rs *KS3Storage) open( } if startOffset != r.Start || (endOffset != 0 && endOffset != r.End+1) { - return nil, r, errors.Annotatef(berrors.ErrStorageUnknown, "open file '%s' failed, expected range: %s, got: %v", - path, *rangeOffset, result.ContentRange) + rangeStr := "" + if result.ContentRange != nil { + rangeStr = *result.ContentRange + } + return nil, r, errors.Annotatef( + berrors.ErrStorageUnknown, + "open file '%s' failed, expected range: %s, got: %s", + path, *rangeOffset, rangeStr) } return result.Body, r, nil diff --git a/br/pkg/storage/s3.go b/br/pkg/storage/s3.go index eaba8f43cf7ca..d14722db55cba 100644 --- a/br/pkg/storage/s3.go +++ b/br/pkg/storage/s3.go @@ -875,8 +875,13 @@ func (rs *S3Storage) open( } if startOffset != r.Start || (endOffset != 0 && endOffset != r.End+1) { - return nil, r, errors.Annotatef(berrors.ErrStorageUnknown, "open file '%s' failed, expected range: %s, got: %v", - path, *rangeOffset, result.ContentRange) + rangeStr := "" + if result.ContentRange != nil { + rangeStr = *result.ContentRange + } + return nil, r, errors.Annotatef(berrors.ErrStorageUnknown, + "open file '%s' failed, expected range: %s, got: %s", + path, *rangeOffset, rangeStr) } return result.Body, r, nil diff --git a/br/pkg/storage/s3_test.go b/br/pkg/storage/s3_test.go index 0f28b9514feb3..09ec2d6bb14ea 100644 --- a/br/pkg/storage/s3_test.go +++ b/br/pkg/storage/s3_test.go @@ -1472,3 +1472,30 @@ func TestS3ReadFileRetryable(t *testing.T) { require.Error(t, err) require.True(t, strings.Contains(err.Error(), errMsg)) } + +func TestOpenRangeMismatchErrorMsg(t *testing.T) { + s := createS3Suite(t) + ctx := aws.BackgroundContext() + start, end := int64(10), int64(30) + + s.s3.EXPECT(). + GetObjectWithContext(ctx, gomock.Any()). + DoAndReturn(func(context.Context, *s3.GetObjectInput, ...request.Option) (*s3.GetObjectOutput, error) { + return &s3.GetObjectOutput{ + ContentRange: aws.String("bytes 10-20/20"), + }, nil + }) + reader, err := s.storage.Open(ctx, "test", &ReaderOption{StartOffset: &start, EndOffset: &end}) + require.ErrorContains(t, err, "expected range: bytes=10-29, got: bytes 10-20/20") + require.Nil(t, reader) + + s.s3.EXPECT(). + GetObjectWithContext(ctx, gomock.Any()). + DoAndReturn(func(context.Context, *s3.GetObjectInput, ...request.Option) (*s3.GetObjectOutput, error) { + return &s3.GetObjectOutput{}, nil + }) + reader, err = s.storage.Open(ctx, "test", &ReaderOption{StartOffset: &start, EndOffset: &end}) + // other function will throw error + require.ErrorContains(t, err, "ContentRange is empty") + require.Nil(t, reader) +}