fish2018/pansou · error

[ ] 读取响应失败

Error message

[%s] 读取响应失败: %w

What it means

Thrown when io.ReadAll(resp.Body) fails after a successful HTTP response from the ouge API. The HTTP layer worked but the response body stream could not be fully read, typically because the connection was reset or closed mid-transfer. The plugin wraps the io error with its plugin name for identification.

Solutions

  1. Retry the search — the error is usually transient connection interruption
  2. Check network stability (VPN/proxy) between the client and woog.nxog.eu.org
  3. Verify the server is not closing connections early (curl -v the same endpoint)
  4. Add a bounded retry with backoff around searchImpl at the caller level

Example fix

// before
body, err := io.ReadAll(resp.Body)
if err != nil { return err }
// after
body, err := io.ReadAll(io.LimitReader(resp.Body, maxBodySize))
if err != nil {
    if errors.Is(err, io.ErrUnexpectedEOF) { return retrySearch() }
    return err
}
Defensive patterns

Strategy: retry

Try / catch

if err != nil {
    if errors.Is(err, io.ErrUnexpectedEOF) || errors.Is(err, syscall.ECONNRESET) {
        return retryWithBackoff(search, 3, 500*time.Millisecond)
    }
    return err
}

Prevention

When it happens

Trigger: searchImpl reads resp.Body after doRequestWithRetry returned 200; the server closes the connection prematurely, a proxy truncates the stream, or the read times out mid-body (unexpected EOF / connection reset by peer).

Common situations: Flaky mobile/VPN connections; large result sets over an unstable link; server-side load balancer idle-timeout killing the connection; gzip/transfer encoding interrupted by a middlebox.

Understand the failure class

Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.

Related errors


AI-assisted analysis of fish2018/pansou@beaa561337 (2026-09-07). Data as JSON: /api/errors/b5d136e7074f2efe. Report an issue: GitHub.

Appendix: source

Thrown at plugin/ouge/ouge.go:149

	// 设置请求头
	req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36")
	req.Header.Set("Accept", "application/json, text/plain, */*")
	req.Header.Set("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8")
	req.Header.Set("Connection", "keep-alive")
	req.Header.Set("Referer", "https://woog.nxog.eu.org/")
	req.Header.Set("Cache-Control", "no-cache")
	
	// 发送请求
	resp, err := p.doRequestWithRetry(req, client)
	if err != nil {
		return nil, fmt.Errorf("[%s] 搜索请求失败: %w", p.Name(), err)
	}
	defer resp.Body.Close()
	
	// 解析JSON响应
	body, err := io.ReadAll(resp.Body)
	if err != nil {
		return nil, fmt.Errorf("[%s] 读取响应失败: %w", p.Name(), err)
	}
	
	var apiResponse OugeAPIResponse
	if err := json.Unmarshal(body, &apiResponse); err != nil {
		return nil, fmt.Errorf("[%s] 解析JSON响应失败: %w", p.Name(), err)
	}
	
	// 检查API响应状态
	if apiResponse.Code != 1 {
		return nil, fmt.Errorf("[%s] API返回错误: %s", p.Name(), apiResponse.Msg)
	}
	
	// 解析搜索结果
	var results []model.SearchResult
	for _, item := range apiResponse.List {
		if result := p.parseAPIItem(item); result.Title != "" {
			results = append(results, result)
		}

View on GitHub (pinned to beaa561337)