{"record":{"id":"cf40867f142be999","repo":"abiosoft/colima","slug":"error-downloading-s-w","errorCode":null,"errorMessage":"error downloading '%s': %w","messagePattern":"error downloading '(.+?)': %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"util/downloader/native.go","lineNumber":57,"sourceCode":"\tfinalURL, err := client.GetFinalURL(ctx, r.URL)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error resolving download URL '%s': %w\", r.URL, err)\n\t}\n\n\t// download the file\n\tresult, err := client.Download(ctx, DownloadOptions{\n\t\tURL:            finalURL,\n\t\tDestPath:       destPath,\n\t\tExpectedETag:   resumeInfo.ETag,\n\t\tResumeFromByte: existingSize,\n\t\tShowProgress:   true,\n\t})\n\tif err != nil {\n\t\t// save resume info for next attempt if we have ETag\n\t\tif result != nil && result.ETag != \"\" {\n\t\t\td.saveResumeInfo(r.URL, result.ETag, existingSize)\n\t\t}\n\t\treturn fmt.Errorf(\"error downloading '%s': %w\", path.Base(r.URL), err)\n\t}\n\n\t// clean up resume info on successful download\n\t_ = os.Remove(resumeInfoPath)\n\n\treturn nil\n}\n","sourceCodeStart":39,"sourceCodeEnd":65,"githubUrl":"https://github.com/abiosoft/colima/blob/c3a5f9184d83a197184f897a9f07eb3c01b3bc88/util/downloader/native.go#L39-L65","documentation":"client.Download failed during the actual GET: a network error mid-transfer, an HTTP status error, or one of the local-file errors from http.go (create/truncate/seek). When the server exposed an ETag, resume info was saved to <cache>.resume so the next attempt continues from the bytes already on disk instead of restarting.","triggerScenarios":"Connection reset/timeout mid-download; the 2-hour context deadline expires on very large files over slow links; disk fills while writing; server aborts the range request.","commonSituations":"Unstable Wi-Fi/VPN; huge images on slow links; proxies killing long transfers; low disk space.","solutions":["Simply retry — resume is automatic when an ETag was captured","Check and free disk space first","For repeated corruption or 416 (Range Not Satisfiable), clear the .resume and .downloading files and start fresh","Stabilize the network or download during off-peak if the 2h timeout is the binding constraint"],"exampleFix":"// before: single attempt, fail hard\nif err := fileDownloader.Download(req, dest); err != nil {\n    return err\n}\n// after: retry loop, network errors only\nvar err error\nfor attempt := 0; attempt < 3; attempt++ {\n    err = fileDownloader.Download(req, dest)\n    if err == nil {\n        break\n    }\n    var ne *downloader.NetworkError\n    if !errors.As(err, &ne) {\n        break\n    }\n    time.Sleep(time.Duration(attempt+1) * 5 * time.Second)\n}\nif err != nil {\n    return err\n}","handlingStrategy":"retry","validationCode":null,"typeGuard":"func isNetworkErr(err error) bool {\n    var ne *downloader.NetworkError\n    return errors.As(err, &ne)\n}","tryCatchPattern":"var err error\nfor attempt := 0; attempt < 3; attempt++ {\n    err = fileDownloader.Download(req, dest)\n    if err == nil {\n        break\n    }\n    if !isNetworkErr(err) {\n        break // local-file or HTTP status errors need human action, not retries\n    }\n    time.Sleep(time.Duration(attempt+1) * 5 * time.Second) // resume continues from .resume info\n}\nif err != nil {\n    return err\n}","preventionTips":["Always retry interrupted downloads — the ETag/.resume mechanism makes retries cheap","Check disk space before starting; a full disk turns every retry into failure","For flaky links, increase attempt counts and backoff rather than disabling resume"],"tags":["network","download","resume","retry"],"backgroundTag":null,"analyzedSha":"c3a5f9184d83a197184f897a9f07eb3c01b3bc88","analyzedAt":"2026-08-15T18:58:08.334Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}