{"record":{"id":"eb86be6c336e9e77","repo":"AlistGo/alist","slug":"task-s-timeout","errorCode":null,"errorMessage":"task %s timeout","messagePattern":"task (.+?) timeout","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"drivers/guangyapan/driver.go","lineNumber":879,"sourceCode":"\t\tif !strings.EqualFold(strings.TrimSpace(out.Msg), \"success\") {\n\t\t\treturn fmt.Errorf(\"get task status failed: %s\", strings.TrimSpace(out.Msg))\n\t\t}\n\t\tswitch out.Data.Status {\n\t\tcase 2:\n\t\t\treturn nil\n\t\tcase -1, 3:\n\t\t\treturn fmt.Errorf(\"task %s failed with status=%d\", taskID, out.Data.Status)\n\t\t}\n\t\tif i == maxTry-1 {\n\t\t\tbreak\n\t\t}\n\t\tselect {\n\t\tcase <-ctx.Done():\n\t\t\treturn ctx.Err()\n\t\tcase <-time.After(interval):\n\t\t}\n\t}\n\treturn fmt.Errorf(\"task %s timeout\", taskID)\n}\n\nfunc (d *GuangYaPan) getUploadToken(ctx context.Context, parentID, name string, size int64) (*uploadTokenData, int, error) {\n\tvar out uploadTokenResp\n\terr := d.postAPI(ctx, \"/nd.bizuserres.s/v1/get_res_center_token\", map[string]any{\n\t\t\"capacity\": 2,\n\t\t\"name\":     name,\n\t\t\"parentId\": parentID,\n\t\t\"res\": map[string]any{\n\t\t\t\"fileSize\": size,\n\t\t},\n\t}, &out)\n\tif err != nil {\n\t\treturn nil, 0, err\n\t}\n\tmsg := strings.TrimSpace(out.Msg)\n\tif msg != \"\" && !strings.EqualFold(msg, \"success\") {\n\t\treturn nil, out.Code, fmt.Errorf(\"get upload token failed: %s\", msg)","sourceCodeStart":861,"sourceCodeEnd":897,"githubUrl":"https://github.com/AlistGo/alist/blob/843d9dc8149126976b2625911e45a4d3ffd6f2f5/drivers/guangyapan/driver.go#L861-L897","documentation":"waitTaskDone exhausted all 30 polls (about 9 seconds) without the task reaching status 2 or a terminal status. The task may still complete server-side; this error only says the driver stopped waiting within its fixed budget.","triggerScenarios":"A task that takes longer than maxTry*interval (30 * 300ms = 9s) to finish: large copies, provider slowness, or a stuck task that never transitions.","commonSituations":"Copying very large files or many files at once; provider under load; the 9-second budget being too tight for big operations.","solutions":["Retry or re-check the operation result - the task often completes after the timeout.","For large copies, expect this timeout and verify the destination afterwards instead of treating it as failure.","Driver maintainers can raise maxTry/interval for large-task workloads."],"exampleFix":"// before\nconst (\n    maxTry   = 30\n    interval = 300 * time.Millisecond\n)\n\n// after - budget scaled to tolerate slow server-side tasks\nconst (\n    maxTry   = 100\n    interval = 500 * time.Millisecond\n)","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"if err := d.waitTaskDone(ctx, taskID); err != nil {\n    if strings.Contains(err.Error(), \"timeout\") {\n        // task may still finish server-side: check destination before retrying\n        if _, lerr := d.listDest(ctx); lerr == nil { return nil }\n        return d.retryCopy(ctx, taskID)\n    }\n    return err\n}","preventionTips":["Treat the ~9s poll budget as advisory; verify outcomes by listing the destination.","Avoid tight retry loops around timeouts - space them out."],"tags":["timeout","task-polling","guangyapan"],"backgroundTag":null,"analyzedSha":"843d9dc8149126976b2625911e45a4d3ffd6f2f5","analyzedAt":"2026-08-15T12:14:11.722Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}