fish2018/pansou · error
HTTP 状态码
Error message
HTTP 状态码 %d
What it means
doRequestWithRetry records a non-nil error from the HTTP attempt; when err == nil but the loop still ended (i.e., the response had a non-acceptable status), it synthesizes "HTTP 状态码 %d" from resp.StatusCode. This becomes the wrapped cause of the final "重试 N 次后仍然失败" error. Note the condition looks inverted at a glance but is correct: it fires only when the attempt returned a response (err == nil) rather than a transport error.
Solutions
- Log each attempt's status code inside the retry loop to see the actual codes received.
- If 403/429, slow down request rate, rotate headers/cookies, or extend backoff between retries.
- If 404, verify the endpoint URL is still valid after a site update.
- Consider treating 4xx as non-retryable to fail fast instead of burning all retries.
Example fix
// before
lastErr = err
if err == nil {
lastErr = fmt.Errorf("HTTP 状态码 %d", resp.StatusCode)
}
// after
if err != nil {
lastErr = err
} else {
lastErr = fmt.Errorf("HTTP 状态码 %d", resp.StatusCode)
} Defensive patterns
Strategy: fallback
Try / catch
resp, err := p.doRequestWithRetry(req, client)
if err != nil {
if strings.Contains(err.Error(), "HTTP 状态码") {
// server kept returning a bad status; do not retry immediately
return nil, fmt.Errorf("endpoint unhealthy: %w", err)
}
return nil, err
} Prevention
- Log each attempt's status code to distinguish persistent blocks from transient 5xx.
- Back off longer between retries when statuses are 403/429.
- Fail fast on 4xx instead of consuming all retries.
When it happens
Trigger: All retry attempts in doRequestWithRetry return responses whose status codes are not accepted by the plugin's success check (e.g. non-200), so the last such status is stored as the sentinel error.
Common situations: Target site persistently returning 403 (anti-bot/WAF), 429 (rate limit) or 5xx across all retries; endpoint moved returning 404; required cookies/headers missing.
Related errors
AI-assisted analysis of fish2018/pansou@beaa561337 (2026-09-07).
Data as JSON: /api/errors/2fbf8894596333a7.
Report an issue: GitHub.
Appendix: source
Thrown at plugin/cyg/cyg.go:395
// 指数退避重试
backoff := time.Duration(1<<uint(i-1)) * 200 * time.Millisecond
time.Sleep(backoff)
}
// 克隆请求避免并发问题
reqClone := req.Clone(req.Context())
resp, err := client.Do(reqClone)
if err == nil && resp.StatusCode == 200 {
return resp, nil
}
if resp != nil {
resp.Body.Close()
}
lastErr = err
if err == nil {
lastErr = fmt.Errorf("HTTP 状态码 %d", resp.StatusCode)
}
}
return nil, fmt.Errorf("重试 %d 次后仍然失败: %w", maxRetries, lastErr)
}
// parseExtOptions 从ext参数中解析搜索选项
func (p *CygPlugin) parseExtOptions(ext map[string]interface{}) CygSearchOptions {
opts := CygSearchOptions{
PerPage: 20,
Page: 1,
OrderBy: "date",
Order: "desc",
}
if ext == nil {
return opts
}View on GitHub (pinned to beaa561337)