fish2018/pansou · error
[ ] search request failed on page
Error message
[%s] search request failed on page %d: %w
What it means
During paginated search, when a page request fails and NO results have been collected yet (allResults is empty), searchImpl returns this wrapped error including the plugin name and page number. If some pages already succeeded, the plugin instead logs a warning and returns partial results — this error only fires on a total failure with nothing to show.
Solutions
- Unwrap the error to identify the root cause (timeout, connection, HTTP error).
- Retry the search; if it's transient, a later attempt may succeed.
- Reduce max_pages or add inter-page delays if throttling is suspected.
- Verify the Discourse base URL and that the instance is reachable from the host.
Example fix
// before
results, err := p.Search(keyword)
if err != nil { return err }
// after
results, err := p.Search(keyword)
if err != nil {
var netErr net.Error
if errors.As(err, &netErr) && netErr.Timeout() {
return retryLater(err) // transient first-page failure
}
return err
} Defensive patterns
Strategy: retry
Validate before calling
resp, err := http.Get(baseURL + "/about.json")
if err != nil {
return fmt.Errorf("discourse instance unreachable before search: %w", err)
}
resp.Body.Close() Try / catch
if err != nil {
var netErr net.Error
if errors.As(err, &netErr) && netErr.Timeout() {
return retryAfterDelay(err, 30*time.Second)
}
return err
} Prevention
- Health-check the Discourse instance before starting paginated searches.
- Cap max_pages and add delays between page requests to avoid throttling.
- Distinguish total failures (this error) from partial failures and handle them separately.
When it happens
Trigger: The HTTP fetch for page currentPage errors while len(allResults) == 0 — e.g. page 1 itself is unreachable, times out, or the scraper fails — so there are no partial results to fall back on.
Common situations: Discourse instance down or DNS broken; first-page request blocked by Cloudflare/rate limiting; max_pages configured but the instance rejects the first request; transient network outage during the initial request.
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/a439dc919f89a202.
Report an issue: GitHub.
Appendix: source
Thrown at plugin/discourse/discourse.go:221
// 循环获取多页
for currentPage := startPage; currentPage < startPage+maxPages; currentPage++ {
fetchedPages++
// 如果不是第一页,添加延迟避免请求过快
if currentPage > startPage {
time.Sleep(pageRequestDelay)
}
searchURL := fmt.Sprintf(searchURLTemplate, encodedKeyword, currentPage)
// 发送搜索请求
resp, err := p.scraper.Get(searchURL)
if err != nil {
// 如果已经获取到一些结果,返回已有结果而不是报错
if len(allResults) > 0 {
fmt.Printf("[%s] Warning: failed to fetch page %d: %v\n", p.Name(), currentPage, err)
break
}
return nil, fmt.Errorf("[%s] search request failed on page %d: %w", p.Name(), currentPage, err)
}
// 检查HTTP状态码
if resp.StatusCode != 200 {
resp.Body.Close()
// 如果已经获取到一些结果,返回已有结果
if len(allResults) > 0 {
fmt.Printf("[%s] Warning: unexpected status code %d on page %d\n", p.Name(), resp.StatusCode, currentPage)
break
}
return nil, fmt.Errorf("[%s] unexpected status code: %d on page %d", p.Name(), resp.StatusCode, currentPage)
}
// 读取响应体
body, err := io.ReadAll(resp.Body)
resp.Body.Close()
if err != nil {
if len(allResults) > 0 {View on GitHub (pinned to beaa561337)