fish2018/pansou · error
HTTP
Error message
HTTP %d
What it means
Internal retry-loop error in fetchBody: a retry attempt received an HTTP response with a non-2xx status code. This becomes lastErr for the attempt and, if all attempts fail, is the cause wrapped in the error returned by fetchDocument. Not normally seen directly by callers.
Solutions
- Note the exact status code: 429 → slow down; 403 → fix headers/cookies; 5xx → upstream outage.
- Update request headers (User-Agent, Referer, cookies) to pass bot checks.
- Lengthen the backoff schedule or retry count for flaky upstreams.
- Verify the URL still exists after any site redesign.
Defensive patterns
Strategy: retry
Validate before calling
resp, err := http.Get(targetURL)
if err == nil && resp.StatusCode != 200 {
log.Printf("upstream status %d before calling plugin", resp.StatusCode)
} Try / catch
if err := fetchDocument(...); err != nil {
if strings.Contains(err.Error(), "HTTP ") {
code := extractStatus(err)
if code == 429 {
time.Sleep(rateLimitCooldown)
}
}
return err
} Prevention
- Throttle request rate to stay under upstream limits (avoid 429)
- Keep cookies/User-Agent fresh to avoid 403
- Use longer exponential backoff for 5xx responses
- Update URLs after site restructures to avoid 404
When it happens
Trigger: fetchBody: client.Do returned no transport error but resp.StatusCode was not a success code on the final attempt; each failing attempt closes the body and backs off exponentially (200ms * 2^attempt).
Common situations: Rate limiting (429), CDN 502/503 during site load spikes, 403 from bot detection or missing cookies, 404 after site URL restructure.
Related errors
AI-assisted analysis of fish2018/pansou@beaa561337 (2026-09-07).
Data as JSON: /api/errors/48faa00236e2bb5a.
Report an issue: GitHub.
Appendix: source
Thrown at plugin/gaoqing888/gaoqing888.go:350
req.Header.Set("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8")
req.Header.Set("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8")
req.Header.Set("Connection", "keep-alive")
req.Header.Set("Referer", referer)
resp, err := client.Do(req)
if err == nil && resp.StatusCode == http.StatusOK {
defer resp.Body.Close()
data, readErr := io.ReadAll(resp.Body)
cancel()
return data, readErr
}
if resp != nil {
resp.Body.Close()
}
if err != nil {
lastErr = err
} else {
lastErr = fmt.Errorf("HTTP %d", resp.StatusCode)
}
cancel()
if attempt < maxRetries-1 {
time.Sleep(200 * time.Millisecond * time.Duration(1<<attempt))
}
}
return nil, lastErr
}
View on GitHub (pinned to beaa561337)