{"record":{"id":"65204c529dbbfcd9","repo":"fish2018/pansou","slug":"w-65204c","errorCode":null,"errorMessage":"读取响应失败: %w","messagePattern":"读取响应失败: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugin/cyg/cyg.go","lineNumber":161,"sourceCode":"\t// 设置请求头\n\tp.setRequestHeaders(req)\n\n\t// 发送请求\n\tresp, err := p.doRequestWithRetry(req, client)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"HTTP请求失败: %w\", err)\n\t}\n\tdefer resp.Body.Close()\n\n\t// 检查状态码\n\tif resp.StatusCode != 200 {\n\t\treturn nil, fmt.Errorf(\"HTTP错误状态码: %d\", resp.StatusCode)\n\t}\n\n\t// 解析响应\n\tbody, err := io.ReadAll(resp.Body)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"读取响应失败: %w\", err)\n\t}\n\n\tvar posts []CygPost\n\tif err := json.Unmarshal(body, &posts); err != nil {\n\t\treturn nil, fmt.Errorf(\"JSON解析失败: %w\", err)\n\t}\n\n\treturn posts, nil\n}\n\n// fetchDownloadLinksAsync 并发获取下载链接\nfunc (p *CygPlugin) fetchDownloadLinksAsync(client *http.Client, posts []CygPost, keyword string) []model.SearchResult {\n\tvar wg sync.WaitGroup\n\tresultChan := make(chan model.SearchResult, len(posts))\n\n\t// 限制并发数量\n\tsemaphore := make(chan struct{}, 10) // 最多10个并发\n","sourceCodeStart":143,"sourceCodeEnd":179,"githubUrl":"https://github.com/fish2018/pansou/blob/beaa56133755a548ebc51b090b3816e2ae044aa6/plugin/cyg/cyg.go#L143-L179","documentation":"After a 200 response, fetchSearchResults reads the body with io.ReadAll; if the read fails mid-stream (connection reset, chunked encoding error, context cancellation), this error wraps the cause. The response arrived but its body could not be fully retrieved.","triggerScenarios":"searchImpl's request gets 200 but the connection drops while reading the body — server closes connection early, network interruption, or the 30s context deadline fires during body read.","commonSituations":"Unstable network or flaky upstream; large responses over unreliable links; proxy terminating long transfers; context timeout too tight for slow responses.","solutions":["Retry the request (doRequestWithRetry covers the send, not the read — wrap read+parse in the retry loop if reads are flaky).","Increase the 30-second context timeout so slow bodies can finish.","Check proxy/CDN behavior that may truncate responses.","Inspect the wrapped error: 'unexpected EOF'/'connection reset' points to server/network, 'context deadline exceeded' to timeout."],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"results, err := plugin.SearchWithResult(ctx, opts)\nif err != nil && strings.Contains(err.Error(), \"读取响应失败\") {\n    // transient I/O failure: safe to retry the whole search\n    results, err = plugin.SearchWithResult(ctx, opts)\n}","preventionTips":["Retry whole requests when body reads fail — they are usually transient","Allow enough context time for large/slow responses","Avoid proxies that truncate long transfers","Monitor the wrapped error for 'context deadline exceeded' to tune timeouts"],"tags":["http","io","network","go"],"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"}