fish2018/pansou · error
[ ] 搜索请求失败
Error message
[%s] 搜索请求失败: %w
What it means
The wuji plugin's searchPage wraps the error from doRequestWithRetry, which performs the HTTP GET (with up to MaxRetries=3 attempts). Any transport-level failure — DNS resolution, TCP connect, TLS handshake, or the 30s context timeout — surfaces here wrapped with the plugin name. This is a client-side/network error, not an HTTP status problem (status codes are handled separately).
Solutions
- Check the wrapped error text to distinguish timeout vs connection-refused vs DNS failure
- Verify the host can reach https://xcili.net (curl -v from the same machine/container)
- Increase TimeoutSeconds or MaxRetries if the site is merely slow
- Configure a proxy for restricted networks (HTTP_PROXY/HTTPS_PROXY) or use a mirror
- If the site is permanently dead, disable the wuji plugin
Defensive patterns
Strategy: retry
Validate before calling
conn, err := net.DialTimeout("tcp", "xcili.net:443", 5*time.Second)
if err != nil {
return fmt.Errorf("wuji upstream unreachable: %w", err)
}
conn.Close() Try / catch
results, err := p.Search(keyword, ext)
if err != nil {
var netErr net.Error
if errors.As(err, &netErr) && netErr.Timeout() {
// retry with backoff or fall back to another plugin
} else if strings.Contains(err.Error(), "搜索请求失败") {
log.Printf("wuji transport error: %v", err)
}
} Prevention
- Treat wuji as one source among many — degrade gracefully instead of failing the whole search
- Ensure the deployment has outbound HTTPS and working DNS
- Increase TimeoutSeconds/MaxRetries for slow networks
- Configure proxy env vars when the site is geo-blocked
When it happens
Trigger: p.doRequestWithRetry(req, client) returns an error after exhausting retries: site unreachable, DNS failure, TLS errors, connection refused/reset, or ctx deadline (TimeoutSeconds=30) exceeded.
Common situations: xcili.net is down, blocked, or geo-restricted from the server running pansou; no outbound internet or broken DNS in a container; corporate firewall/proxy blocking the domain; slow site responses exceeding the 30s timeout repeatedly.
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/1a414bcfbf3725d3.
Report an issue: GitHub.
Appendix: source
Thrown at plugin/wuji/wuji.go:191
searchURL := fmt.Sprintf(SearchURL, encodedKeyword, page)
// 创建带超时的上下文
ctx, cancel := context.WithTimeout(context.Background(), TimeoutSeconds*time.Second)
defer cancel()
// 创建请求
req, err := http.NewRequestWithContext(ctx, "GET", searchURL, nil)
if err != nil {
return nil, fmt.Errorf("[%s] 创建请求失败: %w", p.Name(), err)
}
// 设置请求头
p.setRequestHeaders(req)
// 发送HTTP请求
resp, err := p.doRequestWithRetry(req, client)
if err != nil {
return nil, fmt.Errorf("[%s] 搜索请求失败: %w", p.Name(), err)
}
defer resp.Body.Close()
// 检查状态码
if resp.StatusCode != 200 {
return nil, fmt.Errorf("[%s] 请求返回状态码: %d", p.Name(), resp.StatusCode)
}
// 读取响应体内容
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, fmt.Errorf("[%s] 读取响应失败: %w", p.Name(), err)
}
// 解析HTML
doc, err := goquery.NewDocumentFromReader(strings.NewReader(string(body)))
if err != nil {
return nil, fmt.Errorf("[%s] HTML解析失败: %w", p.Name(), err)View on GitHub (pinned to beaa561337)