{"record":{"id":"5ef537834cd61956","repo":"chenhg5/cc-connect","slug":"read-first-chunk-body-w","errorCode":null,"errorMessage":"read first-chunk body: %w","messagePattern":"read first-chunk body: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"platform/feishu/resource_download.go","lineNumber":163,"sourceCode":"\treq.Header.Set(\"Authorization\", \"Bearer \"+token)\n\treq.Header.Set(\"Range\", \"bytes=0-0\")\n\n\tresp, err := p.resourceDownloadHTTP.Do(req)\n\tif err != nil {\n\t\treturn nil, 0, fmt.Errorf(\"first-chunk request: %w\", err)\n\t}\n\tdefer func() { _, _ = io.Copy(io.Discard, resp.Body); _ = resp.Body.Close() }()\n\n\tswitch resp.StatusCode {\n\tcase http.StatusPartialContent:\n\t\tcr := resp.Header.Get(\"Content-Range\")\n\t\ttotal, ok := parseContentRangeTotal(cr)\n\t\tif !ok {\n\t\t\treturn nil, 0, fmt.Errorf(\"first-chunk: 206 without parseable Content-Range %q\", cr)\n\t\t}\n\t\tbody, err := io.ReadAll(io.LimitReader(resp.Body, 1))\n\t\tif err != nil {\n\t\t\treturn nil, 0, fmt.Errorf(\"read first-chunk body: %w\", err)\n\t\t}\n\t\treturn body, total, nil\n\n\tcase http.StatusOK:\n\t\t// Server ignored Range and sent the full body. We deliberately\n\t\t// honour it and skip the chunked loop — this matches pre-#1741\n\t\t// behaviour for files small enough that Feishu doesn't truncate.\n\t\tbody, err := io.ReadAll(io.LimitReader(resp.Body, p.resourceMaxBytes+1))\n\t\tif err != nil {\n\t\t\treturn nil, 0, fmt.Errorf(\"read full body: %w\", err)\n\t\t}\n\t\tif int64(len(body)) > p.resourceMaxBytes {\n\t\t\treturn nil, 0, fmt.Errorf(\"resource too large: body exceeds cap %d\", p.resourceMaxBytes)\n\t\t}\n\t\treturn body, 0, nil\n\n\tdefault:\n\t\treturn nil, 0, fmt.Errorf(\"first-chunk: unexpected status %d\", resp.StatusCode)","sourceCodeStart":145,"sourceCodeEnd":181,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/platform/feishu/resource_download.go#L145-L181","documentation":"Wraps an io.ReadAll failure while reading the 1-byte first chunk from a 206 Partial Content response body. This is a mid-stream network failure — connection reset, abrupt close, or context cancellation during the read. The library retries via the plain-GET fallback, but persistent transport faults will surface to the caller.","triggerScenarios":"After a successful 206 probe, io.ReadAll(io.LimitReader(resp.Body, 1)) errors: TCP RST, idle timeout, server closing the connection mid-body, or probeCtx cancelled/expired.","commonSituations":"Flaky Wi-Fi/mobile hotspots, aggressive load balancers killing keep-alive connections, Feishu-side transient 5xx close during probe.","solutions":["Retry the download; the resourceRangeChunk path retries transients and resourceSingleGet is attempted as fallback","Check network stability between bot host and Feishu (persistent resets indicate MTU/firewall issues)","If timeouts are the cause, review overall download context deadlines in the calling code"],"exampleFix":"null","handlingStrategy":"retry","validationCode":"null","typeGuard":"null","tryCatchPattern":"var ne net.Error\nif errors.As(err, &ne) || isTransient(err) {\n    time.AfterFunc(backoff, func() { retryDownload(msgID, key, resType) })\n}","preventionTips":["Run the bot on stable network paths; avoid NAT gateways with short idle timeouts","Enable TCP keepalives on the host","Retry downloads on transient errors — the library already retries range chunks, add app-level retry for the probe path","Watch for persistent resets which indicate MTU/firewall problems"],"tags":["go","feishu","network","io"],"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-14T05:17:10.506Z"}