fish2018/pansou · error
page search failed
Error message
page %d search failed: %w
What it means
yunso's Search fans out one goroutine per page; each goroutine calls searchPage and, on any failure, sends a wrapped error into errChan. This message means page N of the paginated search failed; the underlying cause (network, status, parse, API error) is carried by %w. Other pages may still have succeeded — results and errors are collected concurrently.
Solutions
- Read the wrapped cause to see which stage failed (request, status, decode, api error, parse)
- Retry only the failed pages instead of the whole search
- Check whether the keyword triggers an API-side error (api returned error) and adjust the query
- Add per-page retry with backoff before pushing into errChan
- Verify network access to www.yunso.net and its API endpoints
Example fix
// before
items, err := p.searchPage(client, keyword, pageNum)
if err != nil {
errChan <- fmt.Errorf("page %d search failed: %w", pageNum, err)
return
}
// after
var items []YunsoItem
var err error
for attempt := 0; attempt < 3; attempt++ {
items, err = p.searchPage(client, keyword, pageNum)
if err == nil { break }
time.Sleep(time.Duration(attempt+1) * time.Second)
}
if err != nil {
errChan <- fmt.Errorf("page %d search failed: %w", pageNum, err)
return
} Defensive patterns
Strategy: try-catch
Try / catch
items, err := plugin.Search(ctx, keyword)
if err != nil {
var pageErr *PageError
if errors.As(err, &pageErr) {
log.Warn("partial page failure", "page", pageErr.Page, "cause", pageErr.Unwrap())
}
// fall back to partial results already received from resultChan
} Prevention
- Collect partial results even when some pages fail
- Add per-page retry with backoff inside the goroutine
- Cap concurrency to avoid tripping the site's rate limits
- Log wrapped causes with %v on errors.Unwrap
When it happens
Trigger: Any searchPage failure for a given pageNum: HTTP request creation/transport error, non-200 status, body read/decode failure, apiResp.Code != 0, or HTML parse failure, all wrapped as "page N search failed".
Common situations: yunso.net is rate-limiting mid-search so later pages fail, the search API returns an error code (e.g. keyword blocked), or transient network drops cause some pages to fail while others succeed.
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
- page search failed
- 重试 次后仍然失败
- [ ] 搜索第一页失败
- [ ] search request failed on page
- [ ] unexpected status code: on page
AI-assisted analysis of fish2018/pansou@beaa561337 (2026-09-07).
Data as JSON: /api/errors/06f660cfcbc3eabd.
Report an issue: GitHub.
Appendix: source
Thrown at plugin/yunso/yunso.go:108
// SearchWithResult 执行搜索并返回包含 IsFinal 标记的结果
func (p *YunsoAsyncPlugin) SearchWithResult(keyword string, ext map[string]interface{}) (model.PluginSearchResult, error) {
return p.AsyncSearchWithResult(keyword, p.doSearch, p.MainCacheKey, ext)
}
// doSearch 实际搜索实现
func (p *YunsoAsyncPlugin) doSearch(client *http.Client, keyword string, ext map[string]interface{}) ([]model.SearchResult, error) {
resultChan := make(chan []YunsoItem, yunsoDefaultMaxPages)
errChan := make(chan error, yunsoDefaultMaxPages)
var wg sync.WaitGroup
for page := 1; page <= yunsoDefaultMaxPages; page++ {
wg.Add(1)
go func(pageNum int) {
defer wg.Done()
items, err := p.searchPage(client, keyword, pageNum)
if err != nil {
errChan <- fmt.Errorf("page %d search failed: %w", pageNum, err)
return
}
resultChan <- items
}(page)
}
go func() {
wg.Wait()
close(resultChan)
close(errChan)
}()
var allItems []YunsoItem
for items := range resultChan {
allItems = append(allItems, items...)
}
var errs []errorView on GitHub (pinned to beaa561337)