fish2018/pansou · error
[ ] 执行搜索失败
Error message
[%s] 执行搜索失败: %w
What it means
searchImpl wraps any failure from p.executeSearch(keyword) with this error, preserving the underlying cause via %w and prefixing the plugin name. It is the outer boundary error for the first phase of a Diduan search: fetching and extracting the result list.
Solutions
- Unwrap the error (errors.Unwrap or %w chain) to see whether it was a request failure, HTTP status, or parse failure.
- If the message mentions a Cloudflare Managed Challenge, pause and retry later or improve scraper stealth/proxy setup.
- Verify BaseURL/SearchPath still match the live site's endpoints.
- Add retries/backoff for transient network errors.
Example fix
// before
results, err := p.Search(keyword)
if err != nil { return err }
// after
results, err := p.Search(keyword)
if err != nil {
log.Printf("diduan search failed: %v", err) // %w chain shows root cause
return err
} Defensive patterns
Strategy: try-catch
Try / catch
results, err := p.Search(keyword)
if err != nil {
log.Printf("search failed: %+v", err) // preserve wrap chain
if strings.Contains(err.Error(), "Managed Challenge") {
// cool-down / proxy rotation path
}
return err
} Prevention
- Log errors with %+v so the %w chain is preserved for diagnosis.
- Classify wrapped causes (challenge vs status vs network) and handle each distinctly.
- Keep BaseURL/SearchPath updated with the live site.
When it happens
Trigger: executeSearch returns an error — the page request failed (wrapped 搜索请求失败), a non-200 status or Cloudflare challenge occurred (httpStatusError), or goquery HTML parsing failed — and searchImpl propagates it wrapped.
Common situations: Cloudflare challenge pages returned to the scraper; site layout change causing parse or empty responses; network outages; the search endpoint URL changed so requests 404.
Understand the failure class
Background: "API request failed": what wrapped HTTP errors from external APIs mean and how to find the real cause — this error's family across 29 libraries.
Related errors
AI-assisted analysis of fish2018/pansou@beaa561337 (2026-09-07).
Data as JSON: /api/errors/1d9e84b472879220.
Report an issue: GitHub.
Appendix: source
Thrown at plugin/diduan/diduan.go:139
// SearchWithResult 使用 BaseAsyncPlugin 的缓存和后台刷新能力。
func (p *DiduanPlugin) SearchWithResult(keyword string, ext map[string]interface{}) (model.PluginSearchResult, error) {
return p.AsyncSearchWithResult(keyword, p.searchImpl, p.MainCacheKey, ext)
}
// searchImpl 搜索实现
func (p *DiduanPlugin) searchImpl(client *http.Client, keyword string, ext map[string]interface{}) ([]model.SearchResult, error) {
if p.scraper == nil {
return nil, fmt.Errorf("[%s] Cloudflare 请求客户端未初始化", p.Name())
}
if p.debugMode {
log.Printf("[DIDUAN] 开始搜索: %s", keyword)
}
// 第一步:执行搜索获取结果列表
searchResults, err := p.executeSearch(keyword)
if err != nil {
return nil, fmt.Errorf("[%s] 执行搜索失败: %w", p.Name(), err)
}
if p.debugMode {
log.Printf("[DIDUAN] 搜索获取到 %d 个结果", len(searchResults))
}
// 第二步:并发获取详情页链接
finalResults := p.fetchDetailLinks(searchResults, keyword)
if p.debugMode {
log.Printf("[DIDUAN] 最终获取到 %d 个有效结果", len(finalResults))
}
// 第三步:关键词过滤(标准网盘插件需要过滤)
filteredResults := plugin.FilterResultsByKeyword(finalResults, keyword)
if p.debugMode {
log.Printf("[DIDUAN] 关键词过滤后剩余 %d 个结果", len(filteredResults))View on GitHub (pinned to beaa561337)