{"record":{"id":"dfce7e2863c567f7","repo":"chenhg5/cc-connect","slug":"range-request-w","errorCode":null,"errorMessage":"range request: %w","messagePattern":"range request: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"platform/feishu/resource_download.go","lineNumber":332,"sourceCode":"\t\t}\n\n\t\treq, err := http.NewRequestWithContext(ctx, http.MethodGet,\n\t\t\tp.resourceURL(messageID, fileKey, resType), nil)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"build range request: %w\", err)\n\t\t}\n\t\treq.Header.Set(\"Authorization\", \"Bearer \"+token)\n\t\treq.Header.Set(\"Range\", fmt.Sprintf(\"bytes=%d-%d\", start, end))\n\n\t\tresp, err := p.resourceDownloadHTTP.Do(req)\n\t\tif err != nil {\n\t\t\tif isTransientError(err) && attempt < maxTransientRetries {\n\t\t\t\tlastErr = err\n\t\t\t\tslog.Debug(p.tag()+\": transient range chunk error; retrying\",\n\t\t\t\t\t\"attempt\", attempt, \"error\", err, \"start\", start, \"end\", end)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\treturn nil, fmt.Errorf(\"range request: %w\", err)\n\t\t}\n\n\t\tif resp.StatusCode == http.StatusPartialContent {\n\t\t\tcr := resp.Header.Get(\"Content-Range\")\n\t\t\tif cr != \"\" {\n\t\t\t\tif got, ok := parseContentRangeTotal(cr); ok && got != expectedTotal {\n\t\t\t\t\t_ = resp.Body.Close()\n\t\t\t\t\treturn nil, fmt.Errorf(\"Content-Range total mismatch: got %d want %d\", got, expectedTotal)\n\t\t\t\t}\n\t\t\t}\n\t\t\tbody, err := io.ReadAll(io.LimitReader(resp.Body, end-start+1+1))\n\t\t\t_ = resp.Body.Close()\n\t\t\tif err != nil {\n\t\t\t\tif isTransientError(err) && attempt < maxTransientRetries {\n\t\t\t\t\tlastErr = err\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\treturn nil, fmt.Errorf(\"read range body: %w\", err)","sourceCodeStart":314,"sourceCodeEnd":350,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/platform/feishu/resource_download.go#L314-L350","documentation":"The HTTP Range request for a chunk failed at the transport level and the error was not classified as transient (or retries were exhausted), so resourceRangeChunk gives up and wraps it as \"range request\". Transient errors are already retried internally up to maxTransientRetries before this error surfaces.","triggerScenarios":"p.resourceDownloadHTTP.Do fails for a chunk GET — connection reset/refused, TLS handshake error, ctx cancellation/timeout — and isTransientError returns false (or the retry budget maxTransientRetries is spent on repeated transient errors).","commonSituations":"Sustained network outage during a long multi-chunk download; proxy/LB killing long-lived connections; token refresh goroutine cancelled the ctx mid-download; DNS flaps; retries exhausted during a Feishu incident.","solutions":["Retry the whole resourceDownloadStream after checking connectivity — per-chunk retries were exhausted","Inspect the wrapped cause to classify it: connection refused (server/proxy down), timeout (raise timeouts), context cancelled (look for upstream cancellation)","Increase maxTransientRetries or add backoff at the download-stream level for flaky networks","Verify egress to open.feishu.cn and that proxies keep connections alive long enough for each chunk","Ensure the ctx passed in isn't being cancelled early by a parent (e.g. message-handling timeout too short for large files)"],"exampleFix":"// before: short-lived context from message handler\nctx, cancel := context.WithTimeout(parentCtx, 10*time.Second)\n// after: budget proportional to file size\nctx, cancel := context.WithTimeout(parentCtx, 2*time.Minute)","handlingStrategy":"retry","validationCode":"// pre-flight: confirm reachability before a long chunked download\nreq, _ := http.NewRequestWithContext(ctx, http.MethodHead, \"https://open.feishu.cn\", nil)\nif _, err := http.DefaultClient.Do(req); err != nil {\n    return fmt.Errorf(\"feishu unreachable, defer download: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"data, err := p.resourceDownloadStream(ctx, token, msgID, fileKey, resType)\nif err != nil {\n    if strings.Contains(err.Error(), \"range request:\") {\n        // per-chunk retries exhausted; retry the whole download with longer backoff\n        return backoffRetry(ctx, 3, wholeDownload)\n    }\n    return err\n}","preventionTips":["Give chunked downloads a context timeout proportional to total file size","Avoid cancelling the parent ctx (e.g. handler timeout) mid-download","Keep network paths stable: no idle-timeout-killing proxies between the host and Feishu","Tune maxTransientRetries/backoff for known-flaky networks"],"tags":["network","http","retry","chunked-download","feishu"],"backgroundTag":"network-request-failed","analyzedSha":"4000b2338aa6e850c99df54f8b0ed6ed7460b401","analyzedAt":"2026-09-06T11:45:09.575Z","contentChangedAt":"2026-09-06T11:45:09.575Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}