{"record":{"id":"0d1fca5485915a9a","repo":"AlistGo/alist","slug":"wukong-apply-upload-inner-returns-empty-upload-nod","errorCode":null,"errorMessage":"wukong apply upload inner returns empty upload node","messagePattern":"wukong apply upload inner returns empty upload node","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"drivers/wukong/driver.go","lineNumber":351,"sourceCode":"\tup(10)\n\n\tcandidates, err := d.getUploadCandidates(ctx, authToken)\n\tif err != nil {\n\t\treturn err\n\t}\n\tbestHosts := collectCandidateHosts(candidates)\n\tif len(bestHosts) == 0 {\n\t\treturn errors.New(\"wukong upload candidates is empty\")\n\t}\n\tup(20)\n\n\tapplyResp, err := d.applyUploadInner(ctx, authToken, uploadType, size, strings.Join(bestHosts, \",\"))\n\tif err != nil {\n\t\treturn err\n\t}\n\tif len(applyResp.Result.InnerUploadAddress.UploadNodes) == 0 ||\n\t\tlen(applyResp.Result.InnerUploadAddress.UploadNodes[0].StoreInfos) == 0 {\n\t\treturn errors.New(\"wukong apply upload inner returns empty upload node\")\n\t}\n\tnode := applyResp.Result.InnerUploadAddress.UploadNodes[0]\n\tstore := node.StoreInfos[0]\n\tup(30)\n\n\tif size > multipartChunkSize {\n\t\tif err = d.uploadToTOSMultipart(ctx, node.UploadHost, store.StoreURI, store.Auth, getStorageUserID(store.StorageHeader), tempFile, size, up); err != nil {\n\t\t\treturn err\n\t\t}\n\t} else {\n\t\tif _, err = tempFile.Seek(0, io.SeekStart); err != nil {\n\t\t\treturn err\n\t\t}\n\t\treader := &driver.ReaderUpdatingProgress{\n\t\t\tReader: &driver.SimpleReaderWithSize{Reader: tempFile, Size: size},\n\t\t\tUpdateProgress: func(percent float64) {\n\t\t\t\tup(30 + percent*0.5)\n\t\t\t},","sourceCodeStart":333,"sourceCodeEnd":369,"githubUrl":"https://github.com/AlistGo/alist/blob/843d9dc8149126976b2625911e45a4d3ffd6f2f5/drivers/wukong/driver.go#L333-L369","documentation":"Thrown after a successful apply-upload-inner call when the response contains no UploadNodes, or its first node has no StoreInfos. The driver has already picked candidate hosts and applied for an upload slot, but the server did not allocate an upload node (host + StoreURI + auth tuple), so there is nowhere to PUT the bytes.","triggerScenarios":"applyUploadInner returns code 0 but Result.InnerUploadAddress.UploadNodes is empty, or UploadNodes[0].StoreInfos is empty — quota exhaustion, server-side upload capacity issues, an account not entitled to upload, or a response-schema change.","commonSituations":"Wukong account hit a storage/quota limit; uploading unusually large or zero-byte files the backend rejects at apply time; provider API drift; temporary backend incidents.","solutions":["Retry later — transient provisioning failures on the wkbrowser backend produce empty node lists","Check the account's storage quota on pan.wkbrowser.com and free space if full","Update the driver in case the InnerUploadAddress response shape changed","Try a smaller file to distinguish size-dependent rejection from a general failure"],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"if err != nil && strings.Contains(err.Error(), \"empty upload node\") {\n    // re-run full apply flow after delay; nodes are provisioned per-attempt\n    time.Sleep(10 * time.Second)\n    return d.Put(ctx, dstDir, file, up)\n}","preventionTips":["Check account quota before large uploads","Always restart the whole apply flow on failure — never reuse StoreInfos from a failed attempt","Update driver when the wkbrowser upload API changes"],"tags":["wukong","driver","upload","server-side","quota"],"backgroundTag":null,"analyzedSha":"843d9dc8149126976b2625911e45a4d3ffd6f2f5","analyzedAt":"2026-08-15T12:14:11.722Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}