fish2018/pansou · error

request failed (page )

Error message

request failed (page %d): %w

What it means

Hunhepan plugin's paginated search issues this error when http.Client.Do fails for a given page and wraps the original *url.Error. The goroutine sends the wrapped error to errChan and stops processing that page. It is an outbound HTTP transport failure, not an API-level error.

Solutions

  1. Verify network connectivity and DNS resolution for the API host (curl the search URL manually).
  2. Increase the plugin's defaultTimeout since slow upstream responses abort the request context.
  3. Check for proxy/firewall/VPN interference; set HTTPS_PROXY if the environment requires one.
  4. Retry the search; failures here are wrapped per page so check which pageNum failed.

Example fix

// before
resp, err := client.Do(req)
if err != nil {
	errChan <- fmt.Errorf("request failed (page %d): %w", pageNum, err)
	return
}
// after
resp, err := client.Do(req)
if err != nil {
	var netErr net.Error
	if errors.As(err, &netErr) && netErr.Timeout() {
		errChan <- fmt.Errorf("request timed out (page %d): %w", pageNum, err)
	} else {
		errChan <- fmt.Errorf("request failed (page %d): %w", pageNum, err)
	}
	return
}
Defensive patterns

Strategy: retry

Validate before calling

// before calling the plugin
u, err := url.Parse(apiBaseURL)
if err != nil || u.Host == "" {
	return fmt.Errorf("hunhepan API base URL invalid: %w", err)
}
if _, err := net.LookupHost(u.Hostname()); err != nil {
	return fmt.Errorf("cannot resolve hunhepan host %s: %w", u.Hostname(), err)
}

Try / catch

results, err := plugin.Search(ctx, keyword)
if err != nil {
	var netErr net.Error
	if errors.As(err, &netErr) && netErr.Timeout() {
		// retry with a longer timeout or skip this source
	}
	log.Printf("hunhepan page fetch failed, skipping source: %v", err)
}

Prevention

When it happens

Trigger: client.Do(req) returns a non-nil error for page pageNum: DNS resolution failure, connection refused/reset, TLS handshake error, or the per-request context deadline (defaultTimeout) is exceeded before a response is received.

Common situations: The upstream hunhepan API host is down or blocked; DNS cannot resolve the domain; the machine has no network; the timeout is too short for slow responses; a proxy/firewall drops the connection.

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/4e512b1246afe66c. Report an issue: GitHub.

Appendix: source

Thrown at plugin/hunhepan/hunhepan.go:236

			req.Header.Set("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8")

			// 根据不同的API设置不同的Referer
			if strings.Contains(apiURL, "qkpanso.com") {
				req.Header.Set("Referer", "https://qkpanso.com/search")
			} else if strings.Contains(apiURL, "kuake8.com") {
				req.Header.Set("Referer", "https://kuake8.com/search")
			} else if strings.Contains(apiURL, "hunhepan.com") {
				req.Header.Set("Referer", "https://hunhepan.com/search")
			} else if strings.Contains(apiURL, "misoso.cc") {
				req.Header.Set("Referer", "https://www.misoso.cc/search")
				req.Header.Set("Origin", "https://www.misoso.cc")
			}

			// 发送请求
			resp, err := client.Do(req)
			if err != nil {
				debugLog("请求失败 (page %d): %v", pageNum, err)
				errChan <- fmt.Errorf("request failed (page %d): %w", pageNum, err)
				return
			}
			defer resp.Body.Close()

			debugLog("收到响应 (page %d), 状态码: %d", pageNum, resp.StatusCode)

			// 读取响应体
			respBody, err := io.ReadAll(resp.Body)
			if err != nil {
				debugLog("读取响应失败 (page %d): %v", pageNum, err)
				errChan <- fmt.Errorf("read response body failed (page %d): %w", pageNum, err)
				return
			}

			debugLog("响应内容 (page %d, 前500字符): %s", pageNum, string(respBody[:min(500, len(respBody))]))

			// 解析响应
			var apiResp HunhepanResponse

View on GitHub (pinned to beaa561337)