fish2018/pansou · error

HTTP状态码

Error message

HTTP状态码: %d

What it means

Internal retry bookkeeping error in doRequestWithRetry: the HTTP request succeeded but the server returned a status code other than 200. This value becomes lastErr and is surfaced wrapped by the '重试 N 次后仍然失败' error. It is not usually seen directly by callers, only as the wrapped cause.

Solutions

  1. Check the reported status code: 403/429 usually means auth or rate limiting; 5xx means the upstream server is having issues.
  2. Update cookies/User-Agent for the feikuai site if the site tightened bot detection.
  3. Increase backoff between retries or reduce request frequency.
  4. Verify the target URL is still valid (site may have moved, returning 404).
Defensive patterns

Strategy: retry

Validate before calling

resp, err := http.Head(targetURL)
if err == nil && resp.StatusCode >= 400 {
    log.Printf("upstream currently returns %d; skipping attempt", resp.StatusCode)
}

Try / catch

results, err := searchImpl(keyword)
if err != nil {
    var wrapped interface{ Unwrap() error }
    if errors.As(err, &retryErr{}) {
        log.Printf("upstream status issue: %v", err)
        return backoffThenRetryOrFallback()
    }
    return err
}

Prevention

When it happens

Trigger: doRequestWithRetry: client.Do succeeded but resp.StatusCode != 200 on every attempt; the last such status is stored as lastErr.

Common situations: Target site rate-limiting (429), temporary 502/503 from CDN, 403 due to missing/rotated cookies, bot detection returning 4xx/5xx.

Related errors


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

Appendix: source

Thrown at plugin/feikuai/feikuai.go:538

	var lastErr error

	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 {
			if resp.StatusCode == 200 {
				return resp, nil
			}
			resp.Body.Close()
			lastErr = fmt.Errorf("HTTP状态码: %d", resp.StatusCode)
		} else {
			lastErr = err
		}
	}

	return nil, fmt.Errorf("[%s] 重试 %d 次后仍然失败: %w", p.Name(), maxRetries, lastErr)
}

View on GitHub (pinned to beaa561337)