{"record":{"id":"16ddf9344ba75a28","repo":"AlistGo/alist","slug":"url-is-required","errorCode":null,"errorMessage":"url is required","messagePattern":"url is required","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"drivers/123_open/other.go","lineNumber":597,"sourceCode":"\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn okResult{Success: done}, nil\n}\n\n// ---------------------------------------------------------------- offline download\n\n// offlineDownloadArgs is shared by the cloud disk and the image hosting task.\ntype offlineDownloadArgs struct {\n\tURL         string `json:\"url\"`\n\tFileName    string `json:\"file_name\"`\n\tDirID       int64  `json:\"dir_id\"`\n\tCallBackURL string `json:\"call_back_url\"`\n}\n\nfunc (a offlineDownloadArgs) toRequest(args model.OtherArgs) (*pan123.OfflineDownloadRequest, error) {\n\tif a.URL == \"\" {\n\t\treturn nil, errors.New(\"url is required\")\n\t}\n\tdirID := a.DirID\n\tif dirID == 0 && args.Obj != nil && args.Obj.IsDir() {\n\t\tparsed, err := parseFileID(args.Obj.GetID())\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tdirID = parsed\n\t}\n\treturn &pan123.OfflineDownloadRequest{\n\t\tURL:         a.URL,\n\t\tFileName:    a.FileName,\n\t\tDirID:       dirID,\n\t\tCallBackURL: a.CallBackURL,\n\t}, nil\n}\n\ntype taskIDArgs struct {","sourceCodeStart":579,"sourceCodeEnd":615,"githubUrl":"https://github.com/AlistGo/alist/blob/843d9dc8149126976b2625911e45a4d3ffd6f2f5/drivers/123_open/other.go#L579-L615","documentation":"Wrapped error from XunLeiCommon.DeleteOfflineTasks (drivers/thunder/driver.go:659) when the DELETE to TASK_API_URL with task_ids and delete_files fails. The %w keeps the underlying cause; the offending task IDs are included for diagnosis.","triggerScenarios":"Deleting offline tasks when the session/captcha token expired; passing task IDs that were already deleted or belong to another device; delete_files=true while files are locked or being transferred; transient network failure.","commonSituations":"UI double-submits a delete so the second call fails (already-gone IDs); batch deletion of many tasks hitting rate limits; token rotation between listing and deleting.","solutions":["Retry once after refreshing the session if the wrapped cause is auth/captcha related.","Filter task IDs against a fresh GetOfflineTasks listing before deleting to drop already-removed IDs.","For very large batches, chunk the deletion to avoid URL/param length limits and rate limiting.","If delete_files=true consistently fails, retry with delete_files=false to at least remove the task entries, then clean files separately."],"exampleFix":"// before\nerr := xc.DeleteOfflineTasks(ctx, ids, true)\n\n// after: drop stale ids and retry once on auth errors\nlive := filterExistingTasks(ctx, xc, ids)\nerr := xc.DeleteOfflineTasks(ctx, live, true)\nif err != nil && isAuthOrCaptchaErr(errors.Unwrap(err)) {\n\t_ = xc.refreshSession(ctx)\n\terr = xc.DeleteOfflineTasks(ctx, live, true)\n}","handlingStrategy":"validation","validationCode":"// intersect requested IDs with live tasks before deleting\nlive := map[string]bool{}\nif tasks, err := xc.GetOfflineTasks(ctx, token); err == nil {\n\tfor _, t := range tasks {\n\t\tlive[t.ID] = true\n\t}\n}\nvalid := ids[:0]\nfor _, id := range ids {\n\tif live[id] {\n\t\tvalid = append(valid, id)\n\t}\n}","typeGuard":"func isDeleteTasksErr(err error) bool {\n\treturn err != nil && strings.Contains(err.Error(), \"failed to delete tasks\")\n}","tryCatchPattern":"if err := xc.DeleteOfflineTasks(ctx, valid, deleteFiles); isDeleteTasksErr(err) {\n\tif isAuthOrCaptchaErr(errors.Unwrap(err)) {\n\t\t_ = xc.refreshSession(ctx)\n\t\terr = xc.DeleteOfflineTasks(ctx, valid, deleteFiles)\n\t}\n}","preventionTips":["De-duplicate delete requests in the UI to avoid already-deleted IDs.","Filter against a fresh listing before batch deletes.","Chunk large ID batches and add small delays to dodge rate limits."],"tags":["thunder","xunlei","offline-tasks","delete"],"backgroundTag":null,"analyzedSha":"843d9dc8149126976b2625911e45a4d3ffd6f2f5","analyzedAt":"2026-08-15T12:14:11.722Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}