fish2018/pansou · error

read response body failed

Error message

read response body failed (page %d, type %s): %w

What it means

io.ReadAll on the API response body failed, so the raw JSON could not be obtained. The wrapped error (with page/disk type) is sent to errChan. Typically this is a connection dropped mid-body or a truncated/chunked response.

Solutions

  1. Retry the request — this error is usually transient network interruption
  2. Disable HTTP keep-alive connection reuse or set a fresh transport to avoid stale-connection resets
  3. Check proxy/VPN stability if responses are consistently truncated
  4. Increase transport timeouts (ResponseHeaderTimeout, idle conn settings) if applicable

Example fix

// before
respBody, err := io.ReadAll(resp.Body)
if err != nil {
    errChan <- fmt.Errorf("read response body failed (page %d, type %s): %w", pageNum, diskType, err)
    return
}
// after
respBody, err := io.ReadAll(io.LimitReader(resp.Body, 10<<20))
if err != nil {
    errChan <- fmt.Errorf("read response body failed (page %d, type %s): %w", pageNum, diskType, err)
    return // caller should retry this page on transient read errors
}
Defensive patterns

Strategy: retry

Validate before calling

respBody, err := io.ReadAll(io.LimitReader(resp.Body, maxBody))
if err != nil {
    return fmt.Errorf("body read failed (transient?): %w", err)
}

Try / catch

if err != nil {
    if errors.Is(err, io.ErrUnexpectedEOF) || errors.Is(err, context.DeadlineExceeded) {
        // retry the page once
    }
}

Prevention

When it happens

Trigger: The connection is reset or times out while reading resp.Body (server closes early, proxy interference, network interruption during transfer).

Common situations: Unstable network or mobile connection; server/proxy kills long responses; keep-alive connection reused after going stale; response is huge and the read hits a context/transport deadline.

Related errors


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

Appendix: source

Thrown at plugin/sousou/sousou.go:434

				errChan <- fmt.Errorf("request failed (page %d, type %s): %w", pageNum, diskType, err)
				return
			}
			defer resp.Body.Close()

			debugLog("收到响应 (page %d, type %s), 状态码: %d", pageNum, diskType, resp.StatusCode)

			// 检查状态码
			if resp.StatusCode != 200 {
				debugLog("HTTP错误 (page %d, type %s): %d", pageNum, diskType, resp.StatusCode)
				errChan <- fmt.Errorf("HTTP error (page %d, type %s): %d", pageNum, diskType, resp.StatusCode)
				return
			}

			// 读取响应体
			respBody, err := io.ReadAll(resp.Body)
			if err != nil {
				debugLog("读取响应失败 (page %d, type %s): %v", pageNum, diskType, err)
				errChan <- fmt.Errorf("read response body failed (page %d, type %s): %w", pageNum, diskType, err)
				return
			}

			debugLog("响应内容 (page %d, type %s, 前500字符): %s", pageNum, diskType, string(respBody[:min(500, len(respBody))]))

			// 解析响应
			var apiResp SousouResponse
			if err := json.Unmarshal(respBody, &apiResp); err != nil {
				debugLog("JSON解析失败 (page %d, type %s): %v", pageNum, diskType, err)
				errChan <- fmt.Errorf("decode response failed (page %d, type %s): %w", pageNum, diskType, err)
				return
			}

			// 检查响应状态
			if apiResp.Code != 200 {
				debugLog("API返回错误 (page %d, type %s): code=%d, msg=%s", pageNum, diskType, apiResp.Code, apiResp.Msg)
				errChan <- fmt.Errorf("API returned error (page %d, type %s): %s", pageNum, diskType, apiResp.Msg)
				return

View on GitHub (pinned to beaa561337)