fish2018/pansou · error
web search returned status
Error message
web search returned status %d
What it means
searchWeb requires HTTP 200 from the panso.vip web search endpoint. Any other status is converted into 'web search returned status %d' and aborts the web-type search. This is an upstream response-status guard, analogous to error 680 in the Shandian plugin.
Solutions
- Log the status and refresh browser-like headers (User-Agent, Referer, cookies) in setSousouWebHeaders.
- Back off and retry on 429/5xx; these are typically transient.
- Check whether panso.vip changed its search endpoint path and update SousouWebURL.
- Route through a different egress IP/proxy if the IP is blocked by the WAF.
Example fix
// before
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("web search returned status %d", resp.StatusCode)
}
// after
if resp.StatusCode == http.StatusTooManyRequests {
return nil, fmt.Errorf("web search rate limited (429), retry later")
}
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("web search returned status %d", resp.StatusCode)
} Defensive patterns
Strategy: retry
Validate before calling
req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)")
req.Header.Set("Referer", "https://www.panso.vip/") Try / catch
results, err := plugin.Search(keyword)
if err != nil {
var statusErr interface{ Error() string }
if strings.Contains(err.Error(), "web search returned status") {
// backoff on 429/5xx, refresh headers/cookies on 403
}
} Prevention
- Keep browser-like headers current in setSousouWebHeaders
- Back off and jitter retries on 429 instead of hammering
- Rotate egress IPs/proxies if blocked by WAF
- Monitor status codes per source to detect blocking early
When it happens
Trigger: resp.StatusCode != http.StatusOK after client.Do in searchWeb — e.g. 403 from anti-bot protection, 429 rate limit, 5xx upstream error, or 301/302 that the client did not follow.
Common situations: Cloudflare challenge page (403), IP throttled (429), referer/headers in setSousouWebHeaders no longer accepted, site restructured and endpoint removed (404).
Understand the failure class
Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.
Related errors
AI-assisted analysis of fish2018/pansou@beaa561337 (2026-09-07).
Data as JSON: /api/errors/8fc1e476bf176cdf.
Report an issue: GitHub.
Appendix: source
Thrown at plugin/sousou/sousou.go:187
}
func (p *SousouAsyncPlugin) searchWeb(client *http.Client, keyword string) ([]model.SearchResult, error) {
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
searchURL := SousouWebURL + "?q=" + url.QueryEscape(strings.TrimSpace(keyword))
req, err := http.NewRequestWithContext(ctx, http.MethodGet, searchURL, nil)
if err != nil {
return nil, fmt.Errorf("create web search request failed: %w", err)
}
setSousouWebHeaders(req, "https://www.panso.vip/")
resp, err := client.Do(req)
if err != nil {
return nil, fmt.Errorf("web search request failed: %w", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("web search returned status %d", resp.StatusCode)
}
doc, err := goquery.NewDocumentFromReader(resp.Body)
if err != nil {
return nil, fmt.Errorf("parse web search page failed: %w", err)
}
items := make([]pansoSearchItem, 0, 20)
doc.Find("div.search-item").Each(func(_ int, item *goquery.Selection) {
anchor := item.Find("a.search-item-title[href]").First()
href := strings.TrimSpace(anchor.AttrOr("href", ""))
if href == "" {
return
}
items = append(items, pansoSearchItem{
DocURL: absolutePansoURL(href),
Title: strings.TrimSpace(anchor.Text()),
Content: strings.TrimSpace(item.Find(".search-item-info").Text()),View on GitHub (pinned to beaa561337)