From fa43f10af232373b4d724b40dccc73493e25e761 Mon Sep 17 00:00:00 2001 From: Nick Craig-Wood Date: Sat, 5 Sep 2026 11:49:36 +0100 Subject: [PATCH] filescom: fix corrupted uploads after a retried upload error When an upload failed with a retryable error the pacer retried the whole upload with the same input stream. The stream had already been consumed by the first attempt so the retry uploaded an empty file. This fixes it by using CallNoRetry for the upload, as the other backends do, so retryable errors are returned wrapped in a RetryError for the caller to retry the upload with a fresh stream. It also makes 5xx errors from the upload storage servers retryable. These come back from the SDK as a different error type to API errors so were not being retried at all. --- backend/filescom/filescom.go | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/backend/filescom/filescom.go b/backend/filescom/filescom.go index 6e53016d0..63c577e51 100644 --- a/backend/filescom/filescom.go +++ b/backend/filescom/filescom.go @@ -19,6 +19,7 @@ import ( "github.com/Files-com/files-sdk-go/v3/file" file_migration "github.com/Files-com/files-sdk-go/v3/filemigration" "github.com/Files-com/files-sdk-go/v3/folder" + files_sdk_lib "github.com/Files-com/files-sdk-go/v3/lib" "github.com/Files-com/files-sdk-go/v3/session" "github.com/rclone/rclone/fs" "github.com/rclone/rclone/fs/config" @@ -176,6 +177,13 @@ func shouldRetry(ctx context.Context, err error) (bool, error) { } } + // Errors from the upload storage servers are of this type + var httpErr files_sdk_lib.ResponseError + if errors.As(err, &httpErr) && slices.Contains(retryErrorCodes, httpErr.StatusCode) { + fs.Debugf(nil, "Retrying HTTP error %v", err) + return true, err + } + return fserrors.ShouldRetry(err), err } @@ -853,7 +861,7 @@ func (o *Object) Update(ctx context.Context, in io.Reader, src fs.ObjectInfo, op file.UploadWithProvidedMtime(src.ModTime(ctx)), } - err := o.fs.pacer.Call(func() (bool, error) { + err := o.fs.pacer.CallNoRetry(func() (bool, error) { err := o.fs.fileClient.Upload(uploadOpts...) return shouldRetry(ctx, err) })