{"record":{"id":"70674aab3693bff0","repo":"fish2018/pansou","slug":"s-w-70674a","errorCode":null,"errorMessage":"[%s] 读取响应体失败: %w","messagePattern":"\\[(.+?)\\] 读取响应体失败: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugin/dyyj/dyyj.go","lineNumber":279,"sourceCode":"\n\tif p.debugMode {\n\t\tlog.Printf(\"[DYYJ] 搜索请求响应状态码: %d\", resp.StatusCode)\n\t}\n\n\tif resp.StatusCode != 200 {\n\t\tif p.debugMode {\n\t\t\tlog.Printf(\"[DYYJ] 搜索请求HTTP状态错误: %d\", resp.StatusCode)\n\t\t}\n\t\treturn nil, fmt.Errorf(\"[%s] 搜索请求HTTP状态错误: %d\", p.Name(), resp.StatusCode)\n\t}\n\n\t// 读取响应体用于调试\n\tbodyBytes, err := io.ReadAll(resp.Body)\n\tif err != nil {\n\t\tif p.debugMode {\n\t\t\tlog.Printf(\"[DYYJ] 读取响应体失败: %v\", err)\n\t\t}\n\t\treturn nil, fmt.Errorf(\"[%s] 读取响应体失败: %w\", p.Name(), err)\n\t}\n\n\tbodyString := string(bodyBytes)\n\tif p.debugMode {\n\t\tlog.Printf(\"[DYYJ] 响应体大小: %d 字节\", len(bodyString))\n\n\t\t// 保存完整HTML到文件用于分析\n\t\tfilename := fmt.Sprintf(\"./dyyj_search_%s_%d.html\", url.QueryEscape(keyword), time.Now().Unix())\n\t\tif err := os.WriteFile(filename, bodyBytes, 0644); err == nil {\n\t\t\tlog.Printf(\"[DYYJ] 完整HTML已保存到: %s\", filename)\n\t\t} else {\n\t\t\tlog.Printf(\"[DYYJ] 保存HTML文件失败: %v\", err)\n\t\t}\n\n\t\t// 输出HTML的前2000个字符用于调试\n\t\tpreviewLen := 2000\n\t\tif len(bodyString) < previewLen {\n\t\t\tpreviewLen = len(bodyString)","sourceCodeStart":261,"sourceCodeEnd":297,"githubUrl":"https://github.com/fish2018/pansou/blob/beaa56133755a548ebc51b090b3816e2ae044aa6/plugin/dyyj/dyyj.go#L261-L297","documentation":"dyyj.executeSearchHTML could not read the response body: io.ReadAll(resp.Body) returned an error. This means the connection broke mid-body (unexpected EOF, connection reset) or a body-limiting reader failed.","triggerScenarios":"io.ReadAll(resp.Body) failed on a 200 response — server closed the connection mid-transfer, read timeout hit during body streaming, or a custom body-limited reader errored.","commonSituations":"Unstable network or flaky proxy dropping long responses; server-side timeout closing slow connections; body size cap in a wrapping transport exceeded.","solutions":["Simply retry — transient mid-body resets usually succeed on a second attempt","Wrap the body in a size-limited reader (io.LimitReader) and read with a longer deadline","Check proxy stability if a proxy is in the path","Increase client/transport timeouts so slow bodies finish reading"],"exampleFix":"// before\nbodyBytes, err := io.ReadAll(resp.Body)\n// after\nbodyBytes, err := io.ReadAll(io.LimitReader(resp.Body, 10<<20))\nif err != nil && resp.StatusCode == http.StatusOK {\n\t// retry the request once on truncated body\n}","handlingStrategy":"retry","validationCode":"// before calling: ensure client has sane timeouts\nclient := &http.Client{ Timeout: 30 * time.Second }","typeGuard":null,"tryCatchPattern":"bodyBytes, err := io.ReadAll(io.LimitReader(resp.Body, maxBodySize))\nif err != nil {\n\tif errors.Is(err, io.ErrUnexpectedEOF) || errors.Is(err, syscall.ECONNRESET) {\n\t\treturn p.retryOnce(req) // transient truncation: retry\n\t}\n\treturn nil, fmt.Errorf(\"read body failed: %w\", err)\n}","preventionTips":["Cap body reads with io.LimitReader to bound memory and read time","Use clients with explicit timeouts on slow sites","Avoid long-lived flaky proxies; test proxy stability","Retry once on unexpected EOF before surfacing the error"],"tags":["http","network","go","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"}