fish2018/pansou · error

[ ] failed to read response on page

Error message

[%s] failed to read response on page %d: %w

What it means

Wrapped read error in panzun's searchImpl (plugin/panzun/panzun.go:144): the 200 response on a given page could not be fully read. If earlier pages already produced results the loop breaks (partial results kept); otherwise this error is returned, meaning the whole search failed on the first page read.

Solutions

  1. Retry the request — transient read failures usually succeed on a second attempt
  2. Increase the HTTP client/read timeout
  3. Check for proxies or firewalls truncating responses
  4. Rely on partial-results semantics (later pages already break gracefully)

Example fix

// before
return nil, fmt.Errorf("[%s] failed to read response on page %d: %w", p.Name(), page, err)
// after
if len(allResults) == 0 && retryCount < maxRetries {
    return p.searchImplRetry(client, keyword, ext, retryCount+1)
}
return nil, fmt.Errorf("[%s] failed to read response on page %d: %w", p.Name(), page, err)
Defensive patterns

Strategy: retry

Try / catch

results, err := plugin.Search(keyword, ext)
if err != nil {
    if strings.Contains(err.Error(), "failed to read response") {
        // transient I/O error — retry once before giving up
    }
}

Prevention

When it happens

Trigger: The connection drops or times out mid-body transfer (chunked/incomplete response) while reading the panzun.cc discussions API response on the first page.

Common situations: 翻页较深时连接被服务端断开;响应体过大超时。

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/304e9ef3dbce79db. Report an issue: GitHub.

Appendix: source

Thrown at plugin/panzun/panzun.go:144

			return nil, fmt.Errorf("[%s] search request failed on page %d: %w", p.Name(), page, err)
		}

		if resp.StatusCode != http.StatusOK {
			resp.Body.Close()
			if len(allResults) > 0 {
				fmt.Printf("[%s] Warning: unexpected status code %d on page %d\n", p.Name(), resp.StatusCode, page)
				break
			}
			return nil, fmt.Errorf("[%s] unexpected status code: %d on page %d", p.Name(), resp.StatusCode, page)
		}

		body, err := io.ReadAll(resp.Body)
		resp.Body.Close()
		if err != nil {
			if len(allResults) > 0 {
				break
			}
			return nil, fmt.Errorf("[%s] failed to read response on page %d: %w", p.Name(), page, err)
		}

		var searchResp SearchResponse
		if err := jsonutil.Unmarshal(body, &searchResp); err != nil {
			if len(allResults) > 0 {
				break
			}
			return nil, fmt.Errorf("[%s] failed to parse response on page %d: %w", p.Name(), page, err)
		}

		pageResults, err := p.convertDiscussionsToResults(client, searchResp.Data)
		if err != nil {
			fmt.Printf("[%s] Warning: detail parse failed on page %d: %v\n", p.Name(), page, err)
		}

		for _, result := range pageResults {
			if result.UniqueID == "" || seenIDs[result.UniqueID] {
				continue

View on GitHub (pinned to beaa561337)