AlistGo/alist · error

string(data)

Error message

string(data)

What it means

During Cloudreve OneDrive-policy upload, a chunk/callback HTTP response had a status outside {200, 201, 202} and the raw body is returned as the error text. The body is usually the server's or Microsoft Graph's error JSON/HTML, shown verbatim.

Source

Thrown at drivers/cloudreve/util.go:356

		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("[Cloudreve-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(stream.GetSize()))
		}
	}
	// 上传成功发送回调请求
	return d.request(http.MethodPost, "/callback/onedrive/finish/"+u.SessionID, func(req *resty.Request) {
		req.SetBody("{}")
	}, nil)
}

func (d *Cloudreve) upS3(ctx context.Context, stream model.FileStreamer, u UploadInfo, up driver.UpdateProgress) error {
	var finish int64 = 0
	var chunk int = 0
	var etags []string
	DEFAULT := int64(u.ChunkSize)

View on GitHub (pinned to 843d9dc814)

Solutions

  1. Retry the upload as a new OneDrive session — expired upload URLs and stale ranges are the dominant cause.
  2. For 429 responses, wait and retry later; OneDrive throttles aggressive chunk uploads.
  3. Increase chunk size or reduce parallelism so the session completes within its lifetime.
  4. Read the returned body — it usually contains Graph's code/message pinpointing the exact failure.
Defensive patterns

Strategy: try-catch

Type guard

func isGraphErrorBody(body string) bool {
    return strings.Contains(body, "\"error\"") || strings.Contains(body, "service_unavailable")
}

Try / catch

data, _ := io.ReadAll(res.Body)
if res.StatusCode != 200 && res.StatusCode != 201 && res.StatusCode != 202 {
    var g struct{ Error struct{ Code, Message string } }
    if json.Unmarshal(data, &g) == nil && g.Error.Code != "" {
        return fmt.Errorf("onedrive upload %s: %s", g.Error.Code, g.Error.Message)
    }
    return errors.New(string(data))
}

Prevention

When it happens

Trigger: upOneDrive loop: after PUTting a chunk to the OneDrive upload URL (or when a proxy answers), res.StatusCode is e.g. 416/409/429 (not 5xx, which would retry). The body is read and returned untouched.

Common situations: Chunk offsets out of range for the session (416 Requested Range Not Satisfiable) after a resume; OneDrive upload URL expired (sessions live ~15 minutes); 429 throttling without Retry-After being honored; corporate proxy returning an HTML error page.

Related errors


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