fish2018/pansou · error

重试 次后仍然失败

Error message

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

What it means

This error is returned by doRequestWithRetry in the ahhhhfs plugin after all retry attempts to fetch the site have failed. The original error is wrapped with %w, so errors.Is/errors.As can be used to inspect the root cause. It indicates the HTTP request to the source site persistently failed across the full retry budget.

Solutions

  1. Inspect the wrapped lastErr (errors.Unwrap or %v printing) to see the root cause: network unreachable vs timeout vs TLS.
  2. Verify the site URL is reachable from your machine (curl -v the configured base URL) and check DNS/proxy settings.
  3. Increase maxRetries or defaultTimeout in the plugin config if the site is slow but reachable.
  4. If the site blocks automated clients, update request headers (User-Agent, cookies) or use a proxy/mirror URL.
  5. Wait and retry later if the source site itself is temporarily down.

Example fix

// before
results, err := provider.Search(ctx, keyword)
if err != nil {
	log.Fatalf("search failed: %v", err)
}
// after
results, err := provider.Search(ctx, keyword)
if err != nil {
	var netErr net.Error
	if errors.As(err, &netErr) && netErr.Timeout() {
		log.Println("source timed out after retries; retry later or raise timeout")
	} else {
		log.Printf("search failed: %v", err) // root cause preserved via %w
	}
	return
}
Defensive patterns

Strategy: retry

Try / catch

results, err := provider.Search(ctx, keyword)
if err != nil {
	var netErr net.Error
	if errors.As(err, &netErr) && netErr.Timeout() {
		// schedule a later retry with backoff
	} else {
		// surface root cause via errors.Unwrap for diagnostics
	}
}

Prevention

When it happens

Trigger: searchImpl calls doRequestWithRetry, which loops up to maxRetries times; every attempt returns a non-nil error (connection refused, TLS error, timeout, DNS failure), so the loop exits and the plugin returns this wrapped error.

Common situations: The ahhhhfs site is down or blocked by the developer's network/firewall; DNS resolution fails; the site applies anti-bot blocks (403) that retry cannot fix; the configured timeout is too short for a slow connection.

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/e44f4a53ce64e5e1. Report an issue: GitHub.

Appendix: source

Thrown at plugin/ahhhhfs/ahhhhfs.go:535

			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)