{"record":{"id":"a29925891234a364","repo":"AlistGo/alist","slug":"wukong-multipart-transfer-failed-code-d-message","errorCode":null,"errorMessage":"wukong multipart transfer failed: code=%d message=%s part=%d","messagePattern":"wukong multipart transfer failed: code=(.+?) message=(.+?) part=(.+?)","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"drivers/wukong/driver.go","lineNumber":693,"sourceCode":"\t\tSetHeader(\"Content-Crc32\", crc32Hex).\n\t\tSetHeader(\"Content-Length\", strconv.Itoa(len(data))).\n\t\tSetQueryParams(map[string]string{\n\t\t\t\"uploadid\":    uploadID,\n\t\t\t\"part_number\": strconv.Itoa(partNumber),\n\t\t\t\"phase\":       \"transfer\",\n\t\t}).\n\t\tSetBody(data).\n\t\tSetResult(&resp)\n\tif storageUser != \"\" {\n\t\treq.SetHeader(\"X-Storage-U\", storageUser)\n\t}\n\tuploadURL := fmt.Sprintf(\"https://%s/upload/v1/%s\", host, storeURI)\n\t_, err := req.Post(uploadURL)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\tif resp.Code != minUploadSubmitSuccess {\n\t\treturn \"\", fmt.Errorf(\"wukong multipart transfer failed: code=%d message=%s part=%d\", resp.Code, resp.Message, partNumber)\n\t}\n\treturn resp.Data.Crc32, nil\n}\n\nfunc (d *Wukong) finishMultipartUpload(ctx context.Context, host, storeURI, auth, storageUser, uploadID, body string) error {\n\tvar resp tosUploadResp\n\treq := base.NewRestyClient().R().\n\t\tSetContext(ctx).\n\t\tSetHeader(\"Host\", host).\n\t\tSetHeader(\"Referer\", webReferer).\n\t\tSetHeader(\"Origin\", \"https://pan.wkbrowser.com\").\n\t\tSetHeader(\"Authorization\", auth).\n\t\tSetQueryParams(map[string]string{\n\t\t\t\"uploadid\":   uploadID,\n\t\t\t\"phase\":      \"finish\",\n\t\t\t\"uploadmode\": \"part\",\n\t\t}).\n\t\tSetBody(body).","sourceCodeStart":675,"sourceCodeEnd":711,"githubUrl":"https://github.com/AlistGo/alist/blob/843d9dc8149126976b2625911e45a4d3ffd6f2f5/drivers/wukong/driver.go#L675-L711","documentation":"Thrown by uploadMultipartPart when POSTing one part's bytes to https://<host>/upload/v1/<storeURI> gets back a code other than 2000. The part transfer failed at the storage layer; the caller (uploadToTOSMultipart) sees this error and aborts the multipart session.","triggerScenarios":"Part number out of range or already finalized; auth token expiring mid-multipart; part body too large for the host; transient 5xx mapped into the envelope code; uploadID invalidated by a parallel finish/abort.","commonSituations":"Long uploads outliving the token; two clients uploading to the same storeURI; network instability during large parts; host throttling after many rapid parts.","solutions":["Retry the failed part (same uploadID and partNumber) with backoff — most part failures are transient","If the code indicates auth expiry, restart from applyUploadInner for a fresh session","Ensure only one writer uses a given uploadID/storeURI at a time","Reduce multipartChunkSize if hosts reject large single parts"],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"remoteCRC32, err := d.uploadMultipartPart(ctx, host, storeURI, auth, storageUser, uploadID, partNumber, buf, crc32Hex)\nif err != nil {\n    if isTransientTOSCode(err) { // 5xx-ish envelope codes\n        time.Sleep(backoff(partNumber))\n        remoteCRC32, err = d.uploadMultipartPart(ctx, host, storeURI, auth, storageUser, uploadID, partNumber, buf, crc32Hex)\n    }\n    if err != nil { return err }\n}","preventionTips":["Retry individual parts with exponential backoff before failing the session","Ensure exclusive ownership of an uploadID per client","Monitor part failure rate; persistent failures indicate token expiry, not flakiness"],"tags":["wukong","upload","multipart","tos","part","go"],"backgroundTag":null,"analyzedSha":"843d9dc8149126976b2625911e45a4d3ffd6f2f5","analyzedAt":"2026-08-15T12:14:11.722Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}