fish2018/pansou · error

[ ] 请求返回状态码

Error message

[%s] 请求返回状态码: %d

What it means

The kkv plugin rejects any search response whose HTTP status is not 200. After retries succeeded at the transport level, the server returned a non-200 status (e.g. 403 anti-bot, 404 wrong path, 5xx). The plugin treats this as a search failure rather than trying to parse the body.

Solutions

  1. Log resp.StatusCode (the message already contains it) and check which status it is before changing anything
  2. For 403/429: add realistic headers/cookies via setHeaders, slow down request rate, or route through a residential proxy
  3. For 404: inspect the site and update the search URL pattern in the plugin
  4. For 5xx: retry later; the upstream site is degraded
Defensive patterns

Strategy: try-catch

Try / catch

results, err := plugin.Search(ctx, kw)
if err != nil {
    var statusErr interface{ HTTPStatus() int } // or match the '[%s] 请求返回状态码: %d' text
    if strings.Contains(err.Error(), "请求返回状态码") {
        // non-200 from upstream: fall back to another source instead of failing the request
        return fallbackSource.Search(ctx, kw)
    }
    return err
}

Prevention

When it happens

Trigger: doRequestWithRetry returns a response whose resp.StatusCode != 200 for the kkv search URL — most commonly 403 from anti-scraping (Cloudflare), 404 after the site changed its URL structure, or 5xx while the site is degraded.

Common situations: Cloudflare/WAF blocking datacenter IPs (403/429), the source site changed its search path so the old URL 404s, rate limiting after heavy scraping, site maintenance returning 503.

Related errors


AI-assisted analysis of fish2018/pansou@beaa561337 (2026-09-07). Data as JSON: /api/errors/f0e37a08d70d64a8. Report an issue: GitHub.

Appendix: source

Thrown at plugin/kkv/kkv.go:137

	defer cancel()
	
	req, err := http.NewRequestWithContext(ctx, "GET", searchURL, nil)
	if err != nil {
		return nil, fmt.Errorf("[%s] 创建请求失败: %w", p.Name(), err)
	}
	
	p.setHeaders(req, baseURL)
	
	resp, err := p.doRequestWithRetry(req, client)
	if err != nil {
		return nil, fmt.Errorf("[%s] 搜索请求失败: %w", p.Name(), err)
	}
	defer resp.Body.Close()
	
	debugPrintf("📡 HTTP状态码: %d\n", resp.StatusCode)
	
	if resp.StatusCode != 200 {
		return nil, fmt.Errorf("[%s] 请求返回状态码: %d", p.Name(), resp.StatusCode)
	}
	
	doc, err := goquery.NewDocumentFromReader(resp.Body)
	if err != nil {
		return nil, fmt.Errorf("[%s] HTML解析失败: %w", p.Name(), err)
	}
	
	var items []searchItem
	doc.Find("article.post").Each(func(i int, s *goquery.Selection) {
		link := s.Find(".entry-header h2.entry-title a")
		href, exists := link.Attr("href")
		if !exists {
			debugPrintf("⚠️ 第%d个结果没有href属性\n", i+1)
			return
		}
		
		title := strings.TrimSpace(link.Text())
		if title == "" {

View on GitHub (pinned to beaa561337)