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

  1. 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
  2. Verify network connectivity to https://woog.nxog.eu.org/ with curl from the same host
  3. If status-code errors dominate, check for IP bans/rate limiting and use a proxy or updated base URL
  4. 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

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)