chenhg5/cc-connect · error
range request: %w
Error message
range request: %w
What it means
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.
Source
Thrown at platform/feishu/resource_download.go:332
}
req, err := http.NewRequestWithContext(ctx, http.MethodGet,
p.resourceURL(messageID, fileKey, resType), nil)
if err != nil {
return nil, fmt.Errorf("build range request: %w", err)
}
req.Header.Set("Authorization", "Bearer "+token)
req.Header.Set("Range", fmt.Sprintf("bytes=%d-%d", start, end))
resp, err := p.resourceDownloadHTTP.Do(req)
if err != nil {
if isTransientError(err) && attempt < maxTransientRetries {
lastErr = err
slog.Debug(p.tag()+": transient range chunk error; retrying",
"attempt", attempt, "error", err, "start", start, "end", end)
continue
}
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)View on GitHub (pinned to 4000b2338a)
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)
Example fix
// before: short-lived context from message handler ctx, cancel := context.WithTimeout(parentCtx, 10*time.Second) // after: budget proportional to file size ctx, cancel := context.WithTimeout(parentCtx, 2*time.Minute)
Defensive patterns
Strategy: retry
Validate before calling
// pre-flight: confirm reachability before a long chunked download
req, _ := http.NewRequestWithContext(ctx, http.MethodHead, "https://open.feishu.cn", nil)
if _, err := http.DefaultClient.Do(req); err != nil {
return fmt.Errorf("feishu unreachable, defer download: %w", err)
} Try / catch
data, err := p.resourceDownloadStream(ctx, token, msgID, fileKey, resType)
if err != nil {
if strings.Contains(err.Error(), "range request:") {
// per-chunk retries exhausted; retry the whole download with longer backoff
return backoffRetry(ctx, 3, wholeDownload)
}
return err
} Prevention
- 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
When it happens
Trigger: 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).
Common situations: 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.
Related errors
- resource chunk offset=%d: %w
- range chunk retries exhausted
- init failed: %w
- begin failed: %w
- poll failed: %w
AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06).
Data as JSON: /api/errors/dfce7e2863c567f7.
Report an issue: GitHub.