fish2018/pansou · error

重试 次后仍然失败

Error message

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

What it means

Pianku plugin's doRequestWithRetry wraps the last error after exhausting MaxRetries HTTP attempts. It signals that every retry of the request failed (network errors, timeouts, or non-recoverable transport failures), and the final underlying error is preserved via %w. Callers searchImpl and fetchDetailPageLinks propagate this up as a failed search.

Solutions

  1. Check basic connectivity to the target host (curl -v the search URL) to see if the site is reachable from this machine.
  2. Increase MaxRetries and/or the per-request timeout constants in plugin/pianku/pianku.go if failures are transient slowness.
  3. Inspect the wrapped lastErr (errors.Unwrap / %v) to identify the root cause — timeout vs refused vs TLS — and fix accordingly.
  4. Configure a working HTTP proxy for the client if the host is blocked from this network, or rotate exit IPs if rate-limited.

Example fix

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

Strategy: retry

Validate before calling

// pre-check reachability before invoking the plugin search
resp, err := http.Head("https://www.pianku.tv")
if err != nil || resp.StatusCode >= 500 {
    log.Println("pianku site unreachable, skipping search")
    return
}

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 netErr net.Error
    if errors.As(err, &netErr) && netErr.Timeout() {
        // retry later with backoff
    } else {
        log.Printf("pianku search failed permanently: %v", err)
    }
    return fallbackResults, nil
}

Prevention

When it happens

Trigger: Any request issued through doRequestWithRetry (from searchImpl or fetchDetailPageLinks) where all MaxRetries attempts fail with a transport-level error: connection reset, TLS handshake failure, DNS resolution failure, or context deadline exceeded inside the retry loop.

Common situations: Site is down or blocking the scraper (rate limiting, IP ban); corporate proxy/firewall dropping HTTPS; slow network causing per-attempt timeouts; the site changed its TLS config so the client handshake fails repeatedly.

Related errors


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

Appendix: source

Thrown at plugin/pianku/pianku.go:221

			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)
}

// extractSearchResults 提取搜索结果
func (p *PiankuPlugin) extractSearchResults(doc *goquery.Document) []model.SearchResult {
	var results []model.SearchResult
	
	// 查找搜索结果容器
	doc.Find(".sr_lists dl").Each(func(i int, s *goquery.Selection) {
		result := p.extractSingleResult(s)
		if result.UniqueID != "" && len(result.Links) > 0 {
			results = append(results, result)
		}
	})
	
	return results
}

// extractSingleResult 提取单个搜索结果

View on GitHub (pinned to beaa561337)