{"record":{"id":"ff929b07a0b5d9b7","repo":"chenhg5/cc-connect","slug":"read-range-body-w","errorCode":null,"errorMessage":"read range body: %w","messagePattern":"read range body: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"platform/feishu/resource_download.go","lineNumber":350,"sourceCode":"\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)\n\t\t\t}\n\t\t\tif int64(len(body)) != end-start+1 {\n\t\t\t\treturn nil, fmt.Errorf(\"range body length %d != requested %d\", len(body), end-start+1)\n\t\t\t}\n\t\t\treturn body, nil\n\t\t}\n\n\t\t// Non-206 response: capture a snippet for diagnostics, then either\n\t\t// retry (transient 5xx) or fail fast.\n\t\tbody, _ := io.ReadAll(io.LimitReader(resp.Body, 4*1024))\n\t\t_ = resp.Body.Close()\n\n\t\tif resp.StatusCode >= 500 && resp.StatusCode < 600 && attempt < maxTransientRetries {\n\t\t\tlastErr = fmt.Errorf(\"range status %d body=%q\", resp.StatusCode, strings.TrimSpace(string(body)))\n\t\t\tcontinue\n\t\t}\n\n\t\tif resp.StatusCode >= 200 && resp.StatusCode < 300 && end-start+1 == int64(len(body)) {","sourceCodeStart":332,"sourceCodeEnd":368,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/platform/feishu/resource_download.go#L332-L368","documentation":"After receiving a 206 Partial Content response, resourceRangeChunk reads exactly the requested number of bytes (end-start+1 plus one sentinel byte). If io.ReadAll fails mid-read (connection reset, context cancellation, decompression error), the error is wrapped as 'read range body' and returned after transient errors are exhausted.","triggerScenarios":"resourceFetchRemainingChunks -> resourceRangeChunk: the HTTP GET with a Range header returns 206 but the body read fails — network interruption mid-body, server closes connection early, TLS error, or context deadline exceeded during read, after isTransientError retry attempts are used up or the error is non-transient.","commonSituations":"Unstable network/proxy dropping long-running downloads; corporate proxy resetting connections on large bodies; Feishu server closing keep-alive connections; client-side context cancellation.","solutions":["Retry the download; transient read errors are auto-retried up to maxTransientRetries, so persistent failures usually indicate network instability","Reduce chunk size so each range request completes faster and is less exposed to mid-body drops","Check proxy/firewall/VPN stability between the client and Feishu APIs","Inspect the wrapped cause (%w) for context deadline vs connection reset to target the right fix"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// pre-check connectivity to the API host before long downloads\nconn, err := net.DialTimeout(\"tcp\", \"open.feishu.cn:443\", 3*time.Second)\nif err != nil { return fmt.Errorf(\"feishu unreachable: %w\", err) }\nconn.Close()","typeGuard":null,"tryCatchPattern":"if err := downloadResource(fileToken); err != nil {\n    var netErr net.Error\n    if errors.As(err, &netErr) || strings.Contains(err.Error(), \"read range body\") {\n        // transient network issue: retry with backoff\n    }\n}","preventionTips":["Run large downloads on stable networks or with smaller chunk sizes","Avoid aggressive proxies that reset long-running HTTP bodies","Ensure context deadlines are generous enough for full chunk reads","Monitor connection-reset rates to identify network hotspots"],"tags":["http","network","download","io"],"backgroundTag":"http-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"}