AlistGo/alist · error

upload failed after %d retries due to server errors, error %

Error message

upload failed after %d retries due to server errors, error %d

What it means

Fatal retry exhaustion in Cloudreve v4's OneDrive-mediated upload (upOneDrive). Chunk PUTs go straight to the OneDrive session URL; HTTP 500-504 are retried with exponential backoff, and once retries exceed maxRetries the loop aborts with this message embedding the last status code.

Source

Thrown at drivers/cloudreve_v4/util.go:366

			return err
		}
		req = req.WithContext(ctx)
		req.ContentLength = byteSize
		// req.Header.Set("Content-Length", strconv.Itoa(int(byteSize)))
		req.Header.Set("Content-Range", fmt.Sprintf("bytes %d-%d/%d", finish, finish+byteSize-1, file.GetSize()))
		req.Header.Set("User-Agent", d.getUA())
		finish += byteSize
		res, err := base.HttpClient.Do(req)
		if err != nil {
			return err
		}
		// https://learn.microsoft.com/zh-cn/onedrive/developer/rest-api/api/driveitem_createuploadsession
		switch {
		case res.StatusCode >= 500 && res.StatusCode <= 504:
			retryCount++
			if retryCount > maxRetries {
				res.Body.Close()
				return fmt.Errorf("upload failed after %d retries due to server errors, error %d", maxRetries, res.StatusCode)
			}
			backoff := time.Duration(1<<retryCount) * time.Second
			utils.Log.Warnf("[CloudreveV4-OneDrive] server errors %d while uploading, retrying after %v...", res.StatusCode, backoff)
			time.Sleep(backoff)
		case res.StatusCode != 201 && res.StatusCode != 202 && res.StatusCode != 200:
			data, _ := io.ReadAll(res.Body)
			res.Body.Close()
			return errors.New(string(data))
		default:
			res.Body.Close()
			retryCount = 0
			finish += byteSize
			up(float64(finish) * 100 / float64(file.GetSize()))
		}
	}
	// 上传成功发送回调请求
	return d.request(http.MethodPost, "/callback/onedrive/"+u.SessionID+"/"+u.CallbackSecret, func(req *resty.Request) {
		req.SetBody("{}")

View on GitHub (pinned to 843d9dc814)

Solutions

  1. Retry the whole upload later — transient 5xx bursts normally clear
  2. Lengthen or remove proxy timeouts on the upload path
  3. If the session expired, restart the upload for a fresh OneDrive upload session
  4. Reduce chunk size or raise maxRetries to shorten each retry window
Defensive patterns

Strategy: retry

Validate before calling

// pre-flight: ensure chunk size and proxy timeouts are compatible with the OneDrive session lifetime

Try / catch

if err := d.upOneDrive(ctx, file, u, up); err != nil {
    if strings.Contains(err.Error(), "retries due to server errors") {
        u2, err2 := d.getUploadInfo(ctx, file) // fresh session, single retry
        if err2 == nil {
            err = d.upOneDrive(ctx, file, u2, up)
        }
    }
}

Prevention

When it happens

Trigger: Every chunk PUT returns 500-504 more than maxRetries times consecutively: OneDrive degradation/throttling, an expired upload session surfacing as 5xx, or an intermediary proxy synthesizing 502/504 for slow chunk uploads.

Common situations: Large-file uploads during OneDrive incidents; reverse proxies with tight timeouts cutting long chunk PUTs; sessions going stale on very slow connections.

Related errors


AI-assisted analysis of AlistGo/alist@843d9dc814 (2026-08-15). Data as JSON: /api/errors/ce2a57b7e0d4ba2a. Report an issue: GitHub.