fish2018/pansou · error

重试 次后仍然失败

Error message

重试 %d 次后仍然失败: %w

What it means

Qingying plugin's doRequestWithRetry wraps the last error after exhausting maxRetries attempts. It means the request failed on every try with a transport-level error; the final underlying error is preserved via %w. Callers fetchSearchResults and processDetailPage wrap it further.

Solutions

  1. Unwrap lastErr to classify the root cause (errors.As for net.Error timeout, *url.Error, syscall.ECONNREFUSED).
  2. Test the exact URL with curl to confirm whether the site or the local network is at fault.
  3. Increase maxRetries/timeout for transient slowness; add exponential backoff between attempts.
  4. Configure a proxy or rotate exit IPs if the site blocks this client; skip failing URLs gracefully in callers.

Example fix

// before
return nil, fmt.Errorf("重试 %d 次后仍然失败: %w", maxRetries, lastErr)
// after
var nerr net.Error
if errors.As(lastErr, &nerr) && nerr.Timeout() {
    return nil, fmt.Errorf("重试 %d 次后仍然失败(请求超时): %w", maxRetries, lastErr)
}
return nil, fmt.Errorf("重试 %d 次后仍然失败: %w", maxRetries, lastErr)
Defensive patterns

Strategy: fallback

Validate before calling

u, _ := url.Parse(baseURL)
conn, err := net.DialTimeout("tcp", net.JoinHostPort(u.Hostname(), "443"), 5*time.Second)
if err != nil {
    log.Println("site unreachable, using cached results")
    return
}
conn.Close()

Type guard

func isRetryExhausted(err error) bool {
    return err != nil && strings.Contains(err.Error(), "重试")
}

Try / catch

results, err := plugin.Search(keyword)
if err != nil {
    var nerr net.Error
    if errors.As(err, &nerr) && nerr.Timeout() {
        log.Println("qingying timed out after retries; serving cache")
    }
    return cachedResults, nil
}

Prevention

When it happens

Trigger: All maxRetries attempts inside the retry loop returned err — DNS failure, connection refused/reset, TLS error, or per-attempt context timeout — for either the search request or a detail page request.

Common situations: The target site is unreachable from this network (blocked or down); anti-bot drops connections; slow responses exceed the timeout on every attempt; transient ISP/network outage.

Related errors


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

Appendix: source

Thrown at plugin/qingying/qingying.go:448

	for i := 0; i < maxRetries; i++ {
		if i > 0 {
			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
	}
	
	return nil, fmt.Errorf("重试 %d 次后仍然失败: %w", maxRetries, lastErr)
}

View on GitHub (pinned to beaa561337)