{"record":{"id":"b0fb6ac17b8ae82d","repo":"fish2018/pansou","slug":"read-response-body-failed-page-d-type-s-w","errorCode":null,"errorMessage":"read response body failed (page %d, type %s): %w","messagePattern":"read response body failed \\(page (.+?), type (.+?)\\): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugin/sousou/sousou.go","lineNumber":434,"sourceCode":"\t\t\t\terrChan <- fmt.Errorf(\"request failed (page %d, type %s): %w\", pageNum, diskType, err)\n\t\t\t\treturn\n\t\t\t}\n\t\t\tdefer resp.Body.Close()\n\n\t\t\tdebugLog(\"收到响应 (page %d, type %s), 状态码: %d\", pageNum, diskType, resp.StatusCode)\n\n\t\t\t// 检查状态码\n\t\t\tif resp.StatusCode != 200 {\n\t\t\t\tdebugLog(\"HTTP错误 (page %d, type %s): %d\", pageNum, diskType, resp.StatusCode)\n\t\t\t\terrChan <- fmt.Errorf(\"HTTP error (page %d, type %s): %d\", pageNum, diskType, resp.StatusCode)\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\t// 读取响应体\n\t\t\trespBody, err := io.ReadAll(resp.Body)\n\t\t\tif err != nil {\n\t\t\t\tdebugLog(\"读取响应失败 (page %d, type %s): %v\", pageNum, diskType, err)\n\t\t\t\terrChan <- fmt.Errorf(\"read response body failed (page %d, type %s): %w\", pageNum, diskType, err)\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tdebugLog(\"响应内容 (page %d, type %s, 前500字符): %s\", pageNum, diskType, string(respBody[:min(500, len(respBody))]))\n\n\t\t\t// 解析响应\n\t\t\tvar apiResp SousouResponse\n\t\t\tif err := json.Unmarshal(respBody, &apiResp); err != nil {\n\t\t\t\tdebugLog(\"JSON解析失败 (page %d, type %s): %v\", pageNum, diskType, err)\n\t\t\t\terrChan <- fmt.Errorf(\"decode response failed (page %d, type %s): %w\", pageNum, diskType, err)\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\t// 检查响应状态\n\t\t\tif apiResp.Code != 200 {\n\t\t\t\tdebugLog(\"API返回错误 (page %d, type %s): code=%d, msg=%s\", pageNum, diskType, apiResp.Code, apiResp.Msg)\n\t\t\t\terrChan <- fmt.Errorf(\"API returned error (page %d, type %s): %s\", pageNum, diskType, apiResp.Msg)\n\t\t\t\treturn","sourceCodeStart":416,"sourceCodeEnd":452,"githubUrl":"https://github.com/fish2018/pansou/blob/beaa56133755a548ebc51b090b3816e2ae044aa6/plugin/sousou/sousou.go#L416-L452","documentation":"io.ReadAll on the API response body failed, so the raw JSON could not be obtained. The wrapped error (with page/disk type) is sent to errChan. Typically this is a connection dropped mid-body or a truncated/chunked response.","triggerScenarios":"The connection is reset or times out while reading resp.Body (server closes early, proxy interference, network interruption during transfer).","commonSituations":"Unstable network or mobile connection; server/proxy kills long responses; keep-alive connection reused after going stale; response is huge and the read hits a context/transport deadline.","solutions":["Retry the request — this error is usually transient network interruption","Disable HTTP keep-alive connection reuse or set a fresh transport to avoid stale-connection resets","Check proxy/VPN stability if responses are consistently truncated","Increase transport timeouts (ResponseHeaderTimeout, idle conn settings) if applicable"],"exampleFix":"// before\nrespBody, err := io.ReadAll(resp.Body)\nif err != nil {\n    errChan <- fmt.Errorf(\"read response body failed (page %d, type %s): %w\", pageNum, diskType, err)\n    return\n}\n// after\nrespBody, err := io.ReadAll(io.LimitReader(resp.Body, 10<<20))\nif err != nil {\n    errChan <- fmt.Errorf(\"read response body failed (page %d, type %s): %w\", pageNum, diskType, err)\n    return // caller should retry this page on transient read errors\n}","handlingStrategy":"retry","validationCode":"respBody, err := io.ReadAll(io.LimitReader(resp.Body, maxBody))\nif err != nil {\n    return fmt.Errorf(\"body read failed (transient?): %w\", err)\n}","typeGuard":null,"tryCatchPattern":"if err != nil {\n    if errors.Is(err, io.ErrUnexpectedEOF) || errors.Is(err, context.DeadlineExceeded) {\n        // retry the page once\n    }\n}","preventionTips":["Retry page fetches on read errors — they are usually transient","Use io.LimitReader to bound body size","Check proxy/VPN stability if truncation is frequent","Disable stale keep-alive reuse or set MaxIdleConnsPerHost appropriately"],"tags":["network","http","io"],"backgroundTag":"network-request-failed","analyzedSha":"beaa56133755a548ebc51b090b3816e2ae044aa6","analyzedAt":"2026-09-07T00:31:18.025Z","contentChangedAt":"2026-09-07T00:31:18.025Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}