{"record":{"id":"87af90b63f20f8e5","repo":"AlistGo/alist","slug":"instant-upload-returns-empty-task-id","errorCode":null,"errorMessage":"instant upload returns empty task id","messagePattern":"instant upload returns empty task id","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"drivers/guangyapan/driver.go","lineNumber":401,"sourceCode":"\t}\n\tif file.GetSize() < 0 {\n\t\treturn errors.New(\"invalid file size\")\n\t}\n\tname := strings.TrimSpace(file.GetName())\n\tif name == \"\" {\n\t\treturn errors.New(\"file name is empty\")\n\t}\n\n\tparentID := dstDir.GetID()\n\n\ttoken, code, err := d.getUploadToken(ctx, parentID, name, file.GetSize())\n\tif err != nil {\n\t\treturn err\n\t}\n\ttaskID := strings.TrimSpace(token.TaskID)\n\tif code == 156 {\n\t\tif taskID == \"\" {\n\t\t\treturn errors.New(\"instant upload returns empty task id\")\n\t\t}\n\t\treturn d.waitUploadTaskInfo(ctx, taskID)\n\t}\n\n\tif token.ObjectPath == \"\" || token.BucketName == \"\" || token.EndPoint == \"\" || token.AccessKeyID == \"\" || token.SecretAccessKey == \"\" {\n\t\treturn errors.New(\"upload token is incomplete\")\n\t}\n\n\tossEndpoint := normalizeOSSEndpoint(token.EndPoint, token.BucketName)\n\tclient, err := oss.New(ossEndpoint, token.AccessKeyID, token.SecretAccessKey, oss.SecurityToken(token.SessionToken))\n\tif err != nil {\n\t\treturn fmt.Errorf(\"create oss client failed: %w\", err)\n\t}\n\tbucket, err := client.Bucket(token.BucketName)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"create oss bucket failed: %w\", err)\n\t}\n","sourceCodeStart":383,"sourceCodeEnd":419,"githubUrl":"https://github.com/AlistGo/alist/blob/843d9dc8149126976b2625911e45a4d3ffd6f2f5/drivers/guangyapan/driver.go#L383-L419","documentation":"GuangYaPan's getUploadToken returned code 156, which signals instant (seeded) upload — the provider recognized the file hash and skips data transfer — but the accompanying TaskID field was empty. The driver cannot poll waitUploadTaskInfo without a task id, so it aborts rather than assume success.","triggerScenarios":"Uploading a file whose content already exists provider-side (code 156) while the API response omits Data.TaskID — provider inconsistency, race in their seeding pipeline, or a response-shape change.","commonSituations":"Re-uploading a previously uploaded file; uploads during provider maintenance; API version drift where the instant-upload payload no longer includes the task id.","solutions":["Retry the upload once — transient response-shape issues usually resolve","If reproducible, force a non-instant path by changing the file slightly (or wait for provider fix)","Check driver updates: the field mapping of getUploadToken's response may need to track API changes","Report to OpenList maintainers with the raw token response if it persists"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"token, code, err := d.getUploadToken(ctx, parentID, name, size)\nif err != nil { return err }\nif code == 156 && strings.TrimSpace(token.TaskID) == \"\" {\n\t// provider glitch: retry once with a fresh token request\n\ttoken, code, err = d.getUploadToken(ctx, parentID, name, size)\n\tif err != nil { return err }\n}\nreturn d.put(ctx, dstDir, file, up) // proceed with validated token","typeGuard":null,"tryCatchPattern":"if err := d.Put(ctx, dir, file, up); err != nil {\n\tif strings.Contains(err.Error(), \"instant upload returns empty task id\") {\n\t\ttime.Sleep(time.Second)\n\t\treturn d.Put(ctx, dir, file, up) // one bounded retry\n\t}\n\treturn err\n}","preventionTips":["Treat code-156 responses with empty task ids as transient; retry once, not indefinitely","Keep the driver updated — provider response shapes drift","Capture debug logs of the token response when it reproduces and report upstream"],"tags":["guangyapan","upload","instant-upload","api"],"backgroundTag":null,"analyzedSha":"843d9dc8149126976b2625911e45a4d3ffd6f2f5","analyzedAt":"2026-08-15T12:14:11.722Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}