chenhg5/cc-connect · error
read range body: %w
Error message
read range body: %w
What it means
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.
Source
Thrown at platform/feishu/resource_download.go:350
return nil, fmt.Errorf("range request: %w", err)
}
if resp.StatusCode == http.StatusPartialContent {
cr := resp.Header.Get("Content-Range")
if cr != "" {
if got, ok := parseContentRangeTotal(cr); ok && got != expectedTotal {
_ = resp.Body.Close()
return nil, fmt.Errorf("Content-Range total mismatch: got %d want %d", got, expectedTotal)
}
}
body, err := io.ReadAll(io.LimitReader(resp.Body, end-start+1+1))
_ = resp.Body.Close()
if err != nil {
if isTransientError(err) && attempt < maxTransientRetries {
lastErr = err
continue
}
return nil, fmt.Errorf("read range body: %w", err)
}
if int64(len(body)) != end-start+1 {
return nil, fmt.Errorf("range body length %d != requested %d", len(body), end-start+1)
}
return body, nil
}
// Non-206 response: capture a snippet for diagnostics, then either
// retry (transient 5xx) or fail fast.
body, _ := io.ReadAll(io.LimitReader(resp.Body, 4*1024))
_ = resp.Body.Close()
if resp.StatusCode >= 500 && resp.StatusCode < 600 && attempt < maxTransientRetries {
lastErr = fmt.Errorf("range status %d body=%q", resp.StatusCode, strings.TrimSpace(string(body)))
continue
}
if resp.StatusCode >= 200 && resp.StatusCode < 300 && end-start+1 == int64(len(body)) {View on GitHub (pinned to 4000b2338a)
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
Defensive patterns
Strategy: retry
Validate before calling
// pre-check connectivity to the API host before long downloads
conn, err := net.DialTimeout("tcp", "open.feishu.cn:443", 3*time.Second)
if err != nil { return fmt.Errorf("feishu unreachable: %w", err) }
conn.Close() Try / catch
if err := downloadResource(fileToken); err != nil {
var netErr net.Error
if errors.As(err, &netErr) || strings.Contains(err.Error(), "read range body") {
// transient network issue: retry with backoff
}
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: Unstable network/proxy dropping long-running downloads; corporate proxy resetting connections on large bodies; Feishu server closing keep-alive connections; client-side context cancellation.
Understand the failure class
Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.
Related errors
AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06).
Data as JSON: /api/errors/ff929b07a0b5d9b7.
Report an issue: GitHub.