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

  1. Retry the request (doRequestWithRetry covers the send, not the read — wrap read+parse in the retry loop if reads are flaky).
  2. Increase the 30-second context timeout so slow bodies can finish.
  3. Check proxy/CDN behavior that may truncate responses.
  4. 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

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)