fish2018/pansou · error
[ ] 搜索请求失败
Error message
[%s] 搜索请求失败: %w
What it means
The ouge plugin wraps any error returned by its retrying HTTP request layer into a plugin-tagged error via fmt.Errorf with %w. It means the search request to https://woog.nxog.eu.org/ could not be completed after all internal retries. The wrapped cause (DNS failure, timeout, connection refused, non-200 after retries) is preserved and should be inspected with errors.Unwrap or errors.As.
Solutions
- Inspect the wrapped cause with errors.Unwrap(err) or log the full chain to see if it is DNS, timeout, or an HTTP status error
- Verify network connectivity to https://woog.nxog.eu.org/ with curl from the same host
- If status-code errors dominate, check for IP bans/rate limiting and use a proxy or updated base URL
- Increase the HTTP client timeout if the cause is a context/deadline exceeded
Example fix
// before
results, err := plugin.Search(keyword)
if err != nil { return err }
// after
results, err := plugin.Search(keyword)
if err != nil {
var httpErr interface{ Unwrap() error }
if errors.As(err, &httpErr) { log.Printf("cause: %v", errors.Unwrap(err)) }
return fmt.Errorf("ouge search unavailable: %w", err)
} Defensive patterns
Strategy: retry
Validate before calling
// check connectivity before calling
func checkOugeReachable() error {
c, err := net.DialTimeout("tcp", "woog.nxog.eu.org:443", 3*time.Second)
if err != nil { return err }
c.Close()
return nil
} Try / catch
if err != nil {
var netErr net.Error
if errors.As(err, &netErr) && netErr.Timeout() {
return fallbackSearch(keyword) // alternate plugin
}
log.Printf("ouge search failed: %v (cause: %v)", err, errors.Unwrap(err))
return err
} Prevention
- Pre-flight check host reachability before batch searches
- Always unwrap and log the %w cause for diagnosis
- Keep a fallback search plugin for when this upstream is down
- Monitor for status-code-heavy failures indicating IP bans
When it happens
Trigger: searchImpl calls p.doRequestWithRetry(req, client) and that returns non-nil err: network unreachable, DNS resolution failure, TLS errors, timeouts, or repeated non-200 responses (which become 'HTTP状态码: %d' and are themselves wrapped here).
Common situations: The woog.nxog.eu.org mirror is down or blocked in the user's region; no internet/DNS in a container; corporate proxy intercepts TLS; server rate-limits and returns 403/429 on every attempt.
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/d1fce1ab6c4fddfe.
Report an issue: GitHub.
Appendix: source
Thrown at plugin/ouge/ouge.go:142
defer cancel()
req, err := http.NewRequestWithContext(ctx, "GET", searchURL, nil)
if err != nil {
return nil, fmt.Errorf("[%s] 创建搜索请求失败: %w", p.Name(), err)
}
// 设置请求头
req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36")
req.Header.Set("Accept", "application/json, text/plain, */*")
req.Header.Set("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8")
req.Header.Set("Connection", "keep-alive")
req.Header.Set("Referer", "https://woog.nxog.eu.org/")
req.Header.Set("Cache-Control", "no-cache")
// 发送请求
resp, err := p.doRequestWithRetry(req, client)
if err != nil {
return nil, fmt.Errorf("[%s] 搜索请求失败: %w", p.Name(), err)
}
defer resp.Body.Close()
// 解析JSON响应
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, fmt.Errorf("[%s] 读取响应失败: %w", p.Name(), err)
}
var apiResponse OugeAPIResponse
if err := json.Unmarshal(body, &apiResponse); err != nil {
return nil, fmt.Errorf("[%s] 解析JSON响应失败: %w", p.Name(), err)
}
// 检查API响应状态
if apiResponse.Code != 1 {
return nil, fmt.Errorf("[%s] API返回错误: %s", p.Name(), apiResponse.Msg)
}View on GitHub (pinned to beaa561337)