fish2018/pansou · error
获取searchid失败
Error message
获取searchid失败: %v
What it means
ClxiongPlugin.SearchWithResult fails in its first phase: p.getSearchID(keyword) could not obtain the searchid token needed for the two-step search (POST to get a 302 redirect whose Location header carries the searchid, then GET results). The underlying cause is wrapped with %v (loses errors.Is/As chains) and, when debugMode is on, also logged. Without a searchid the second GET cannot proceed, so Search fails entirely.
Solutions
- Enable debugMode or inspect the wrapped error to see the underlying cause (transport failure vs unexpected status).
- If the inner error is "期望302重定向" with a 200 status, the site likely changed flow or is serving an anti-bot page — capture the response body and update getSearchID accordingly.
- Check connectivity and rate limits; slow down request frequency if 429 appears.
- Increase timeouts/retries in getSearchID if the POST intermittently times out.
- Prefer %w over %v when wrapping so callers can use errors.Is on the root cause.
Example fix
// before
return nil, fmt.Errorf("获取searchid失败: %v", err)
// after
return nil, fmt.Errorf("获取searchid失败: %w", err) // enables errors.Is/As on the root cause Defensive patterns
Strategy: try-catch
Validate before calling
// ensure keyword is usable before the two-step flow
if strings.TrimSpace(keyword) == "" { return nil, errors.New("keyword required") } Try / catch
results, err := plugin.Search(ctx, keyword)
if err != nil {
if strings.Contains(err.Error(), "获取searchid失败") {
// first phase failed: check wrapped cause; retry once after backoff
time.Sleep(2 * time.Second)
results, err = plugin.Search(ctx, keyword)
}
if err != nil { return nil, err }
} Prevention
- Use %w instead of %v when wrapping so callers can inspect root causes.
- Enable debugMode during integration to capture getSearchID internals.
- Monitor for site flow changes — a 200 response where 302 was expected means the flow changed.
- Throttle requests to avoid rate-limit-triggered failures in phase one.
When it happens
Trigger: Search -> SearchWithResult -> getSearchID returns an error: the POST timed out, connection failed, retry budget exhausted, or the server responded with a status other than 301/302 (or an empty Location header). SearchWithResult then returns fmt.Errorf("获取searchid失败: %v", err).
Common situations: The clxiong endpoint stopped issuing 302 redirects after a site update; anti-bot protection returns 200 with a challenge page instead of a redirect; rate limiting returns 429; the environment cannot reach the site (offline/CI).
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/99d5ba79ee02bc73.
Report an issue: GitHub.
Appendix: source
Thrown at plugin/clxiong/clxiong.go:71
if err != nil {
return nil, err
}
return result.Results, nil
}
// SearchWithResult 搜索并返回详细结果
func (p *ClxiongPlugin) SearchWithResult(keyword string, ext map[string]interface{}) (*model.PluginSearchResult, error) {
if p.debugMode {
log.Printf("[CLXIONG] 开始搜索: %s", keyword)
}
// 第一步:POST搜索获取searchid
searchID, err := p.getSearchID(keyword)
if err != nil {
if p.debugMode {
log.Printf("[CLXIONG] 获取searchid失败: %v", err)
}
return nil, fmt.Errorf("获取searchid失败: %v", err)
}
// 第二步:GET搜索结果
results, err := p.getSearchResults(searchID, keyword)
if err != nil {
if p.debugMode {
log.Printf("[CLXIONG] 获取搜索结果失败: %v", err)
}
return nil, err
}
// 第三步:同步获取详情页磁力链接
results = p.fetchDetailLinksSync(results)
if p.debugMode {
log.Printf("[CLXIONG] 搜索完成,获得 %d 个结果", len(results))
}
View on GitHub (pinned to beaa561337)