chenhg5/cc-connect · error
read full body: %w
Error message
read full body: %w
What it means
Wraps an io.ReadAll failure while reading a full 200 body (server ignored Range) up to resourceMaxBytes+1 bytes in resourceFetchFirstChunk. Same class of transport failure as the first-chunk read error but on the whole-body path; it can also fire when the download context is cancelled while streaming a large body.
Source
Thrown at platform/feishu/resource_download.go:173
case http.StatusPartialContent:
cr := resp.Header.Get("Content-Range")
total, ok := parseContentRangeTotal(cr)
if !ok {
return nil, 0, fmt.Errorf("first-chunk: 206 without parseable Content-Range %q", cr)
}
body, err := io.ReadAll(io.LimitReader(resp.Body, 1))
if err != nil {
return nil, 0, fmt.Errorf("read first-chunk body: %w", err)
}
return body, total, nil
case http.StatusOK:
// Server ignored Range and sent the full body. We deliberately
// honour it and skip the chunked loop — this matches pre-#1741
// behaviour for files small enough that Feishu doesn't truncate.
body, err := io.ReadAll(io.LimitReader(resp.Body, p.resourceMaxBytes+1))
if err != nil {
return nil, 0, fmt.Errorf("read full body: %w", err)
}
if int64(len(body)) > p.resourceMaxBytes {
return nil, 0, fmt.Errorf("resource too large: body exceeds cap %d", p.resourceMaxBytes)
}
return body, 0, nil
default:
return nil, 0, fmt.Errorf("first-chunk: unexpected status %d", resp.StatusCode)
}
}
// resourceFetchRemainingChunks loops Range GETs starting after the first
// byte, concatenates them with `first`, and verifies the total size matches
// what the probe advertised.
func (p *Platform) resourceFetchRemainingChunks(ctx context.Context, token, messageID, fileKey, resType string, total int64, first []byte) ([]byte, error) {
buf := bytes.NewBuffer(make([]byte, 0, total))
buf.Write(first)
View on GitHub (pinned to 4000b2338a)
Solutions
- Retry the download once connectivity is stable
- Check for idle-connection killing middleboxes; raise keepalive/idle timeouts
- Ensure callers don't cancel the context prematurely for large files
Example fix
null
Defensive patterns
Strategy: retry
Validate before calling
null
Type guard
null
Try / catch
if err != nil && strings.Contains(err.Error(), "read full body") {
select {
case <-ctx.Done(): return ctx.Err()
case <-time.After(retryDelay):
return retryDownload(ctx, msgID, key, resType)
}
} Prevention
- Don't cancel the download context while a large file is still streaming unless truly superseded
- Keep connections alive long enough for the largest expected file over the slowest expected link
- Check middlebox idle-timeout settings for long transfers
- Prefer the chunked path succeeding (Range honoured) over huge single 200 bodies
When it happens
Trigger: Server returned 200 with the full body and the stream breaks mid-read: connection reset, TLS truncation, parent context cancelled, or read deadline hit on a large slow transfer.
Common situations: Downloading large files over unstable networks, NAT/firewall idle timeouts dropping long-lived connections, or user-triggered cancellation (message superseded) aborting the stream.
Related errors
- first-chunk request: %w
- read first-chunk body: %w
- HTTP GET %s: %w
- read body from %s: %w
- openai tts: read audio: %w
AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06).
Data as JSON: /api/errors/ae788c5e1a2cc247.
Report an issue: GitHub.