diff --git a/br/pkg/restore/import_retry_test.go b/br/pkg/restore/import_retry_test.go
index cc31edf23a0e9..509ac3bbd0c13 100644
--- a/br/pkg/restore/import_retry_test.go
+++ b/br/pkg/restore/import_retry_test.go
@@ -599,3 +599,25 @@ func TestFilterFilesByRegion(t *testing.T) {
 		require.Equal(t, subfile, c.subfiles)
 	}
 }
+
+func TestRetryRecognizeErrCode(t *testing.T) {
+	waitTime := 1 * time.Millisecond
+	maxWaitTime := 16 * time.Millisecond
+	ctx := context.Background()
+	inner := 0
+	outer := 0
+	utils.WithRetry(ctx, func() error {
+		e := utils.WithRetry(ctx, func() error {
+			inner++
+			e := status.Error(codes.Unavailable, "the connection to TiKV has been cut by a neko, meow :3")
+			if e != nil {
+				return errors.Trace(e)
+			}
+			return nil
+		}, utils.NewBackoffer(10, waitTime, maxWaitTime, utils.NewErrorContext("download sst", 3)))
+		outer++
+		return errors.Trace(e)
+	}, utils.NewBackoffer(10, waitTime, maxWaitTime, utils.NewErrorContext("import sst", 3)))
+	require.Equal(t, 10, outer)
+	require.Equal(t, 100, inner)
+}
diff --git a/br/pkg/restore/log_client/BUILD.bazel b/br/pkg/restore/log_client/BUILD.bazel
new file mode 100644
index 0000000000000..e69de29bb2d1d
diff --git a/br/pkg/utils/backoff.go b/br/pkg/utils/backoff.go
index c0828ffb291ea..80930f35ae5e4 100644
--- a/br/pkg/utils/backoff.go
+++ b/br/pkg/utils/backoff.go
@@ -14,6 +14,7 @@ import (
 	"github.com/pingcap/failpoint"
 	"github.com/pingcap/log"
 	berrors "github.com/pingcap/tidb/br/pkg/errors"
+	"go.uber.org/multierr"
 	"go.uber.org/zap"
 	"google.golang.org/grpc/codes"
 	"google.golang.org/grpc/status"
@@ -184,12 +185,14 @@ func NewBackupSSTBackoffer() Backoffer {
 
 func (bo *importerBackoffer) NextBackoff(err error) time.Duration {
 	// we don't care storeID here.
-	res := bo.errContext.HandleErrorMsg(err.Error(), 0)
+	errs := multierr.Errors(err)
+	lastErr := errs[len(errs)-1]
+	res := bo.errContext.HandleErrorMsg(lastErr.Error(), 0)
 	if res.Strategy == RetryStrategy {
 		bo.delayTime = 2 * bo.delayTime
 		bo.attempt--
 	} else {
-		e := errors.Cause(err)
+		e := errors.Cause(lastErr)
 		switch e { // nolint:errorlint
 		case berrors.ErrKVEpochNotMatch, berrors.ErrKVDownloadFailed, berrors.ErrKVIngestFailed, berrors.ErrPDLeaderNotFound:
 			bo.delayTime = 2 * bo.delayTime
@@ -204,7 +207,7 @@ func (bo *importerBackoffer) NextBackoff(err error) time.Duration {
 				bo.delayTime = 2 * bo.delayTime
 				bo.attempt--
 			case codes.Canceled:
-				if isGRPCCancel(err) {
+				if isGRPCCancel(lastErr) {
 					bo.delayTime = 2 * bo.delayTime
 					bo.attempt--
 				} else {