fish2018/pansou · error
[ ] 请求失败,重试 次后仍失败
Error message
[%s] 请求失败,重试%d次后仍失败: %w
What it means
Final failure of doRequestWithRetry: after maxRetries attempts (with 100ms sleeps between them) the request never succeeded, so the last error is wrapped with the plugin name and the retry count via %w. Callers receive this from searchImpl as the cause of error 470.
Solutions
- Look at the wrapped cause (errors.Unwrap) to distinguish network failure from status failure
- Wait and retry later with a longer backoff than the built-in 100ms
- Test reachability of https://woog.nxog.eu.org/ independently (curl, DNS lookup)
- If rate limiting, reduce request frequency or add jitter/proxy rotation before retrying
Example fix
// before
if err != nil { return err }
// after
var retried *RetryExhaustedError
if errors.As(err, &retried) {
time.Sleep(2 * time.Second)
return secondAttempt()
} Defensive patterns
Strategy: fallback
Validate before calling
func hostUp(host string) bool {
c, err := net.DialTimeout("tcp", host+":443", 3*time.Second)
if err != nil { return false }
c.Close()
return true
} Try / catch
if err != nil {
if strings.Contains(err.Error(), "重试") { // retries exhausted
return alternatePluginSearch(keyword) // fallback source
}
return err
} Prevention
- Don't hammer immediately after this error — the built-in backoff is only 100ms
- Add exponential backoff with jitter at the caller level
- Maintain a fallback plugin/source for resilience
- Alert on persistent retry exhaustion — it means the upstream is down, not flaky
When it happens
Trigger: All attempts in the retry loop fail — persistent network errors, timeouts, or repeated non-200 statuses (error 474) — then the loop exits and this error is returned.
Common situations: The API host is fully down or DNS-blackholed; aggressive rate limiting survives the 100ms backoff; firewall blocks outbound HTTPS; the 100ms fast-retry policy is too short for a temporarily degraded upstream.
Understand the failure class
Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.
Related errors
AI-assisted analysis of fish2018/pansou@beaa561337 (2026-09-07).
Data as JSON: /api/errors/fce74bdc09c150dc.
Report an issue: GitHub.
Appendix: source
Thrown at plugin/ouge/ouge.go:423
for i := 0; i < maxRetries; i++ {
resp, err := client.Do(req)
if err == nil {
if resp.StatusCode == http.StatusOK {
return resp, nil
}
resp.Body.Close()
lastErr = fmt.Errorf("HTTP状态码: %d", resp.StatusCode)
} else {
lastErr = err
}
// JSON API快速重试:只等待很短时间
if i < maxRetries-1 {
time.Sleep(100 * time.Millisecond) // 从秒级改为100毫秒
}
}
return nil, fmt.Errorf("[%s] 请求失败,重试%d次后仍失败: %w", p.Name(), maxRetries, lastErr)
}
// GetPerformanceStats 获取性能统计信息
func (p *OugeAsyncPlugin) GetPerformanceStats() map[string]interface{} {
totalRequests := atomic.LoadInt64(&searchRequests)
totalTime := atomic.LoadInt64(&totalSearchTime)
var avgTime float64
if totalRequests > 0 {
avgTime = float64(totalTime) / float64(totalRequests) / 1e6 // 转换为毫秒
}
return map[string]interface{}{
"search_requests": totalRequests,
"avg_search_time_ms": avgTime,
"total_search_time_ns": totalTime,
}
}View on GitHub (pinned to beaa561337)