fish2018/pansou · error

[ ] token请求失败

Error message

[%s] token请求失败: %w

What it means

getToken wraps the error returned by doRequestWithRetry, which performed the token page GET and exhausted its retry loop (connection errors, timeouts, TLS failures). The token could not be fetched from the remote site, so searchImpl cannot proceed. The wrapped cause is the last network error observed across all retries.

Solutions

  1. Unwrap and log the inner error (%w chain) to see the concrete cause (timeout vs refused vs TLS)
  2. Verify network reachability: curl the token URL from the same host, check DNS and proxy settings (HTTP_PROXY/HTTPS_PROXY)
  3. Increase the 30s context timeout or the retry count/backoff in doRequestWithRetry if upstream is slow
  4. Check whether the site requires cookies/anti-bot handling that redirects in a way the client rejects

Example fix

null
Defensive patterns

Strategy: retry

Validate before calling

// pre-check reachability
conn, err := net.DialTimeout("tcp", host+":443", 5*time.Second)
if err != nil { return fmt.Errorf("unreachable: %w", err) }
conn.Close()

Try / catch

if err != nil {
    var ne net.Error
    if errors.As(err, &ne) && ne.Timeout() {
        return retryWithBackoff(ctx)
    }
    return nil, fmt.Errorf("token fetch failed permanently: %w", err)
}

Prevention

When it happens

Trigger: p.doRequestWithRetry(req, client) returns an error — all retry attempts to GET the token page failed (dial errors, context deadline of the 30s timeout, TLS handshake failure, connection reset).

Common situations: Target site blocked/down or geo-restricted; corporate proxy/firewall intercepting; DNS failure; client timeout too short for a slow upstream; missing proxy env config.

Related errors


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

Appendix: source

Thrown at plugin/xys/xys.go:163

	defer cancel()

	req, err := http.NewRequestWithContext(ctx, "GET", tokenURL, nil)
	if err != nil {
		return "", fmt.Errorf("[%s] 创建token请求失败: %w", p.Name(), err)
	}

	// 设置完整的请求头
	req.Header.Set("User-Agent", UserAgent)
	req.Header.Set("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8")
	req.Header.Set("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8")
	req.Header.Set("Connection", "keep-alive")
	req.Header.Set("Upgrade-Insecure-Requests", "1")
	req.Header.Set("Cache-Control", "max-age=0")
	req.Header.Set("Referer", BaseURL+"/")

	resp, err := p.doRequestWithRetry(req, client)
	if err != nil {
		return "", fmt.Errorf("[%s] token请求失败: %w", p.Name(), err)
	}
	defer resp.Body.Close()

	if resp.StatusCode != 200 {
		return "", fmt.Errorf("[%s] token请求HTTP状态错误: %d", p.Name(), resp.StatusCode)
	}

	// 解析HTML提取token
	doc, err := goquery.NewDocumentFromReader(resp.Body)
	if err != nil {
		return "", fmt.Errorf("[%s] 解析token页面HTML失败: %w", p.Name(), err)
	}

	// 查找script标签中的DToken定义
	var token string
	doc.Find("script").Each(func(i int, s *goquery.Selection) {
		scriptContent := s.Text()
		if strings.Contains(scriptContent, "DToken") {

View on GitHub (pinned to beaa561337)