{"record":{"id":"5bbcd1974c657a8c","repo":"AlistGo/alist","slug":"chunk-d-giving-up-after-d-retries-while-server","errorCode":null,"errorMessage":"chunk_%d: giving up after %d retries while server is overloaded","messagePattern":"chunk_(.+?): giving up after (.+?) retries while server is overloaded","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/net/request.go","lineNumber":370,"sourceCode":"\t\t// If this occurs we unwrap the err to set the underlying error\n\t\t// and attempt any remaining retries.\n\t\tif e, ok := err.(*errNeedRetry); ok {\n\t\t\terr = e.Unwrap()\n\t\t\tif n > 0 {\n\t\t\t\t// 测试：下载时 断开 alist向云盘发起的下载连接\n\t\t\t\t// 校验：下载完后校验文件哈希值 一致\n\t\t\t\td.incrWritten(n)\n\t\t\t\tch.start += n\n\t\t\t\tch.size -= n\n\t\t\t\tparams.Range.Start = ch.start\n\t\t\t\tparams.Range.Length = ch.size\n\t\t\t}\n\t\t\tlog.Warnf(\"err chunk_%d, object part download error %s, retrying attempt %d. %v\",\n\t\t\t\tch.id, params.URL, retry, err)\n\t\t} else if err == errOverloadRetry {\n\t\t\toverloadRetry++\n\t\t\tif overloadRetry > d.cfg.PartBodyMaxRetries*10 {\n\t\t\t\terr = fmt.Errorf(\"chunk_%d: giving up after %d retries while server is overloaded\", ch.id, overloadRetry)\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tbackoff := time.Duration(overloadRetry) * 100 * time.Millisecond\n\t\t\tif backoff > 2*time.Second {\n\t\t\t\tbackoff = 2 * time.Second\n\t\t\t}\n\t\t\tselect {\n\t\t\tcase <-d.ctx.Done():\n\t\t\t\treturn d.ctx.Err()\n\t\t\tcase <-time.After(backoff):\n\t\t\t}\n\t\t\tretry--\n\t\t\tcontinue\n\t\t} else {\n\t\t\tbreak\n\t\t}\n\t}\n","sourceCodeStart":352,"sourceCodeEnd":388,"githubUrl":"https://github.com/AlistGo/alist/blob/843d9dc8149126976b2625911e45a4d3ffd6f2f5/internal/net/request.go#L352-L388","documentation":"Emitted by the chunk download loop when errOverloadRetry (a 429/502/503/504-class response on a non-first chunk) has been retried more than PartBodyMaxRetries*10 times. The loop backs off linearly (100ms per attempt, capped at 2s) and then gives up, converting a persistent server-overload condition into a hard failure for that chunk.","triggerScenarios":"A remote server continuously returning 429/502/503/504 for chunk ranges; PartBodyMaxRetries configured very low so the *10 budget is small; a proxy or CDN throttling the client for the whole download duration.","commonSituations":"Cloud drive rate limiting sustained over minutes; upstream outage during a large file download; aggressive CDN throttle on ranged requests.","solutions":["Retry the whole download later with backoff — the server is overloaded, not the client broken.","Raise cfg.PartBodyMaxRetries to enlarge the overload retry budget.","Reduce chunk concurrency to lower request pressure on the server.","Check whether the storage endpoint has known rate limits and space requests accordingly."],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":"strings.Contains(err.Error(), \"giving up after\")","tryCatchPattern":"err := download()\nif err != nil && strings.Contains(err.Error(), \"server is overloaded\") {\n    // exponential backoff at the task level, retry whole download later\n    scheduleRetry(2*time.Minute)\n}","preventionTips":["Tune PartBodyMaxRetries relative to how long your upstream throttles.","Reduce chunk concurrency to avoid triggering 429s in the first place.","Apply whole-task backoff when overload errors repeat, not immediate tight retries."],"tags":["network","download","retry","rate-limit","backoff","go"],"backgroundTag":null,"analyzedSha":"843d9dc8149126976b2625911e45a4d3ffd6f2f5","analyzedAt":"2026-08-15T12:14:11.722Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}