fish2018/pansou · error
读取响应失败
Error message
读取响应失败: %w
What it means
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.
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.
Defensive patterns
Strategy: retry
Try / catch
results, err := plugin.SearchWithResult(ctx, opts)
if err != nil && strings.Contains(err.Error(), "读取响应失败") {
// transient I/O failure: safe to retry the whole search
results, err = plugin.SearchWithResult(ctx, opts)
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: Unstable network or flaky upstream; large responses over unreliable links; proxy terminating long transfers; context timeout too tight for slow responses.
Related errors
AI-assisted analysis of fish2018/pansou@beaa561337 (2026-09-07).
Data as JSON: /api/errors/65204c529dbbfcd9.
Report an issue: GitHub.
Appendix: source
Thrown at plugin/cyg/cyg.go:161
// 设置请求头
p.setRequestHeaders(req)
// 发送请求
resp, err := p.doRequestWithRetry(req, client)
if err != nil {
return nil, fmt.Errorf("HTTP请求失败: %w", err)
}
defer resp.Body.Close()
// 检查状态码
if resp.StatusCode != 200 {
return nil, fmt.Errorf("HTTP错误状态码: %d", resp.StatusCode)
}
// 解析响应
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, fmt.Errorf("读取响应失败: %w", err)
}
var posts []CygPost
if err := json.Unmarshal(body, &posts); err != nil {
return nil, fmt.Errorf("JSON解析失败: %w", err)
}
return posts, nil
}
// fetchDownloadLinksAsync 并发获取下载链接
func (p *CygPlugin) fetchDownloadLinksAsync(client *http.Client, posts []CygPost, keyword string) []model.SearchResult {
var wg sync.WaitGroup
resultChan := make(chan model.SearchResult, len(posts))
// 限制并发数量
semaphore := make(chan struct{}, 10) // 最多10个并发
View on GitHub (pinned to beaa561337)