fish2018/pansou · error
读取验证响应失败
Error message
读取验证响应失败: %w
What it means
The verification response body could not be read: io.ReadAll(resp.Body) failed after a successful HTTP exchange, so solveVerification wraps the error as 读取验证响应失败. This indicates the connection dropped mid-body or the server sent a malformed/truncated stream.
Solutions
- Retry the whole verification flow (getDetailInfo already retries alternate candidate URLs)
- Increase the request timeout so the read isn't cut off by ctx deadline
- Verify no proxy/middlebox truncates responses; test with curl
- Check the wrapped error — 'unexpected EOF' vs 'context deadline exceeded' points to different fixes
Defensive patterns
Strategy: retry
Try / catch
info, err := plugin.GetDetailInfo(ctx, url)
if err != nil && strings.Contains(err.Error(), "读取验证响应失败") {
time.Sleep(time.Second)
info, err = plugin.GetDetailInfo(ctx, url) // transient read failures usually succeed on retry
} Prevention
- Retry truncated reads — they are usually transient
- Use longer timeouts so body reads are not cut off by the context
- Check proxy/middlebox configuration if truncation recurs on the same host
When it happens
Trigger: io.ReadAll(resp.Body) errors in solveVerification — server closed the connection prematurely, chunked encoding interrupted, or a proxy reset the stream during the challenge response download.
Common situations: Unstable network or flaky CDN; aggressive server-side connection limits killing keep-alive connections; middleboxes/proxies truncating responses; response is huge and the timeout/context expires mid-read.
Understand the failure class
Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.
Related errors
AI-assisted analysis of fish2018/pansou@beaa561337 (2026-09-07).
Data as JSON: /api/errors/875971902b1f317b.
Report an issue: GitHub.
Appendix: source
Thrown at plugin/qiwei/qiwei.go:400
query.Set("value", encodedValue)
verifyURL += "?" + query.Encode()
ctx, cancel := context.WithTimeout(context.Background(), detailTimeout)
defer cancel()
req, err := http.NewRequestWithContext(ctx, http.MethodGet, verifyURL, nil)
if err != nil {
return fmt.Errorf("创建验证请求失败: %w", err)
}
p.setHeaders(req, pageURL)
req.Header.Set("X-Requested-With", "XMLHttpRequest")
resp, err := p.doRequestWithRetry(req, client)
if err != nil {
return fmt.Errorf("提交验证失败: %w", err)
}
defer resp.Body.Close()
responseBody, err := io.ReadAll(resp.Body)
if err != nil {
return fmt.Errorf("读取验证响应失败: %w", err)
}
if isVerifyPage(string(responseBody)) {
return fmt.Errorf("站点未接受验证参数")
}
return nil
}
func md5StringToHex(value string) string {
var builder strings.Builder
for _, r := range value {
builder.WriteString(fmt.Sprintf("%d", r+1))
}
sum := md5.Sum([]byte(builder.String()))
return hex.EncodeToString(sum[:])
}
func (p *QiweiPlugin) parseDetail(detailURL, body, fallbackTitle, fallbackPic string) (detailInfo, error) {
doc, err := goquery.NewDocumentFromReader(strings.NewReader(body))View on GitHub (pinned to beaa561337)