fish2018/pansou · error
[ ] hsid= 读取响应失败
Error message
[%s] hsid=%s读取响应失败: %w
What it means
This error is thrown by fetchShareLink when the body of the (HTTP 200) share-link response cannot be read via io.ReadAll, e.g. the connection was closed mid-body or a decompression error occurred. It wraps the underlying read error with the plugin name and hsid.
Solutions
- Retry the whole fetchShareLink call — the error is usually transient
- Check proxy/LB idle timeout settings vs server response time
- Verify any forced compression/decompression (Transport.DisableCompression) configuration
- Increase maxRetries in doRequestWithRetry for flaky networks
Example fix
// before
body, err := io.ReadAll(resp.Body)
if err != nil {
return "", "", fmt.Errorf("[%s] hsid=%s读取响应失败: %w", p.Name(), hsid, err)
}
// after
body, err := io.ReadAll(io.LimitReader(resp.Body, 1<<20))
if err != nil {
return "", "", fmt.Errorf("[%s] hsid=%s读取响应失败: %w", p.Name(), hsid, err)
}
if len(body) == 0 {
return "", "", fmt.Errorf("[%s] hsid=%s响应体为空", p.Name(), hsid)
} Defensive patterns
Strategy: retry
Validate before calling
// nothing to validate pre-call; transient I/O error // defend by limiting read size and checking for empty bodies afterward
Try / catch
body, err := io.ReadAll(io.LimitReader(resp.Body, 1<<20))
if err != nil {
return fmt.Errorf("read share-link response failed: %w", err)
} Prevention
- Retry the whole request — mid-body failures are usually transient
- Check LB/proxy idle timeouts against upstream latency
- Cap body reads with io.LimitReader to avoid pathological responses
- Monitor error rates to detect persistent network degradation
When it happens
Trigger: io.ReadAll(resp.Body) returns an error inside fetchShareLink — network interruption or connection reset while reading the response body.
Common situations: Flaky mobile/proxied networks dropping connections mid-transfer; server closing keep-alive connections early; responses with broken gzip/deflate encoding; LB idle timeouts.
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/e9b15064c8f11ca4.
Report an issue: GitHub.
Appendix: source
Thrown at plugin/haisou/haisou.go:415
req.Header.Set("Connection", "keep-alive")
req.Header.Set("Referer", "https://haisou.cc/")
// 发送HTTP请求(带重试机制)
resp, err := p.doRequestWithRetry(req, client)
if err != nil {
return "", "", fmt.Errorf("[%s] hsid=%s链接请求失败: %w", p.Name(), hsid, err)
}
defer resp.Body.Close()
// 检查状态码
if resp.StatusCode != 200 {
return "", "", fmt.Errorf("[%s] hsid=%s链接请求返回状态码: %d", p.Name(), hsid, resp.StatusCode)
}
// 读取响应体
body, err := io.ReadAll(resp.Body)
if err != nil {
return "", "", fmt.Errorf("[%s] hsid=%s读取响应失败: %w", p.Name(), hsid, err)
}
// 解析响应
var apiResp FetchAPIResponse
if err := json.Unmarshal(body, &apiResp); err != nil {
return "", "", fmt.Errorf("[%s] hsid=%s链接JSON解析失败: %w", p.Name(), hsid, err)
}
// 检查API响应状态
if apiResp.Code != 0 {
return "", "", fmt.Errorf("[%s] hsid=%s链接API错误: %s", p.Name(), hsid, apiResp.Msg)
}
// 根据平台类型构建完整的分享链接
shareURL := buildShareURL(platform, apiResp.Data.ShareCode)
if shareURL == "" {
return "", "", fmt.Errorf("[%s] hsid=%s不支持的网盘平台: %s", p.Name(), hsid, platform)
}View on GitHub (pinned to beaa561337)