{"record":{"id":"811d79a34bf73868","repo":"AlistGo/alist","slug":"canceled","errorCode":null,"errorMessage":"canceled","messagePattern":"canceled","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"internal/offline_download/guangyapan/guangyapan.go","lineNumber":121,"sourceCode":"\t\treturn nil, errors.New(\"GuangYaPan offline download only supports GuangYaPan destination storage\")\n\t}\n\ttasks, err := g.GetTasks(driver, task.GID)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tstatus := &tool.Status{\n\t\tStatus: \"the task has been deleted\",\n\t}\n\tfor _, t := range tasks {\n\t\tif t.TaskID != task.GID {\n\t\t\tcontinue\n\t\t}\n\t\tstatus.Progress = float64(t.Progress)\n\t\tstatus.TotalBytes = t.TotalSize\n\t\tstatus.Completed = t.Status == offlineStatusCompleted || t.Status == offlineStatusPartiallyCompleted\n\t\tstatus.Status = taskStatusText(t)\n\t\tif t.Status == offlineStatusFailed || t.Status == offlineStatusCanceled {\n\t\t\tstatus.Err = errors.New(status.Status)\n\t\t}\n\t\treturn status, nil\n\t}\n\tstatus.Err = errors.New(\"the task has been deleted\")\n\treturn status, nil\n}\n\nfunc init() {\n\ttool.Tools.Add(&GuangYaPan{})\n}\n","sourceCodeStart":103,"sourceCodeEnd":132,"githubUrl":"https://github.com/AlistGo/alist/blob/843d9dc8149126976b2625911e45a4d3ffd6f2f5/internal/offline_download/guangyapan/guangyapan.go#L103-L132","documentation":"Status maps offlineStatusCanceled to status.Err with the bare text \"canceled\". This means the task was canceled on the provider side (by a user in the GuangYaPan app, by quota policy, or by an earlier DeleteOfflineTasks call) rather than failing on its own. The wrapper cannot distinguish who canceled it.","triggerScenarios":"Polling GuangYaPan.Status when t.Status == offlineStatusCanceled — e.g. someone canceled the task in the provider's own UI, or a Remove/retry flow deleted it while the status poller still tracks it.","commonSituations":"Task canceled in the GuangYaPan app by another session; a concurrent Remove(task) racing a Status poll; provider auto-cancel on duplicate tasks.","solutions":["If the task was intentionally canceled, delete the local task record so polling stops","If canceled by mistake, re-add the URL via AddURL","Avoid calling Remove and Status concurrently for the same GID"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"if st.Err != nil && st.Status == \"canceled\" {\n    // distinguish cancel from failure for UX\n    markTaskCanceled(task) // do not show as error\n}","preventionTips":["Do not call Remove and Status concurrently for the same task","Serialize lifecycle transitions per GID (add/remove/poll) with a per-task lock","If cancellation is unexpected, audit other sessions using the same provider account"],"tags":["offline-download","guangyapan","canceled-task"],"backgroundTag":null,"analyzedSha":"843d9dc8149126976b2625911e45a4d3ffd6f2f5","analyzedAt":"2026-08-15T12:14:11.722Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}