fish2018/pansou · error
重试 次后仍然失败
Error message
重试 %d 次后仍然失败
What it means
Companion to error 37: when the retry loop in ash's doRequestWithRetry ends with lastErr == nil — which happens when the loop broke early because req.Context().Err() != nil (context cancelled or deadline exceeded) — the function still must return an error, so it returns '重试 %d 次后仍然失败' without a wrapped cause.
Solutions
- Increase the 15s context timeout in searchImpl to accommodate total backoff + slow responses.
- Check req.Context().Err() and include it in the error so the cause is not lost.
- Reduce per-attempt cost (fewer header round-trips, HTTP/2 keep-alive) so the deadline suffices.
- Distinguish cancellation from timeout in callers to skip pointless re-wrapping.
Example fix
// before
return nil, fmt.Errorf("重试 %d 次后仍然失败", maxRetries)
// after
if ctxErr := req.Context().Err(); ctxErr != nil {
return nil, fmt.Errorf("重试 %d 次后仍然失败: %w", maxRetries, ctxErr)
}
return nil, fmt.Errorf("重试 %d 次后仍然失败", maxRetries) Defensive patterns
Strategy: retry
Validate before calling
// ensure budget fits: totalBackoff + attempts*perReqTimeout < ctxDeadline
if maxRetries*retryDelay >= 15*time.Second { reduce retries or raise deadline } Try / catch
if err != nil && errors.Is(err, context.DeadlineExceeded) {
// treat as timeout: increase deadline or reduce work per attempt
return partialResults, err
} Prevention
- Size context deadlines to exceed worst-case retry totals
- Propagate cancellation intent so timeout vs cancel is distinguishable
- Reduce backoff ceiling when contexts are short
- Include ctx.Err() in the final error for diagnosability
When it happens
Trigger: The 15-second context from searchImpl expires (or is cancelled) while attempts are still failing/ongoing, so the loop breaks via the ctx.Err() check with no lastErr recorded — ash.go:307.
Common situations: Slow upstream site that cannot answer within 15s under current backoff; caller cancelled the search; environment with high latency to the target region.
Understand the failure class
Background: Request timed out: what client-side request timeouts mean across libraries (Request timed out, TIMED_OUT, APITimeoutError) — this error's family across 39 libraries.
Related errors
AI-assisted analysis of fish2018/pansou@beaa561337 (2026-09-07).
Data as JSON: /api/errors/f68747450384b450.
Report an issue: GitHub.
Appendix: source
Thrown at plugin/ash/ash.go:307
// 清理响应
if resp != nil {
resp.Body.Close()
}
lastErr = err
// 如果是上下文取消或超时,不再重试
if req.Context().Err() != nil {
break
}
}
if lastErr != nil {
return nil, fmt.Errorf("重试 %d 次后仍然失败: %w", maxRetries, lastErr)
}
return nil, fmt.Errorf("重试 %d 次后仍然失败", maxRetries)
}
View on GitHub (pinned to beaa561337)