fish2018/pansou · error
请求网站首页失败
Error message
请求网站首页失败: %w
What it means
findPotentialActionIDs fetches the target site's homepage with an HTTP client to discover Next.js action IDs. When the HTTP transport itself fails (DNS resolution failure, connection refused/reset, TLS handshake error, timeout), the underlying error is wrapped with this message via %w so callers can unwrap it with errors.Is/As. It means the site could not be reached at all — no response was received.
Solutions
- Verify basic connectivity to the site domain first: curl -v https://<site-homepage>/ and compare the error.
- Check proxy/VPN requirements — set HTTP_PROXY/HTTPS_PROXY or configure the client's Transport with a Proxy function if the site is unreachable directly.
- Check whether the plugin's configured base URL/domain is up to date; the site may have moved to a new domain.
- Retry after a delay if it is a transient timeout; consider adding a timeout with retries in the caller (discoverActionIDs).
- Inspect the wrapped error with errors.Unwrap / *url.Error to distinguish DNS vs connection vs TLS causes.
Example fix
// before
resp, err := client.Do(req)
if err != nil {
return nil, fmt.Errorf("请求网站首页失败: %w", err)
}
// after
resp, err := client.Do(req)
if err != nil {
var urlErr *url.Error
if errors.As(err, &urlErr) {
return nil, fmt.Errorf("请求网站首页失败: %w (阶段: %s)", err, urlErr.Op)
}
return nil, fmt.Errorf("请求网站首页失败: %w", err)
} Defensive patterns
Strategy: retry
Validate before calling
url := "https://<site-homepage>/"
if u, err := neturl.Parse(url); err != nil || u.Scheme == "" || u.Host == "" {
return fmt.Errorf("invalid site URL: %q", url)
}
conn, err := net.DialTimeout("tcp", net.JoinHostPort(u.Hostname(), portOrDefault(u)), 5*time.Second)
if err != nil {
return fmt.Errorf("site unreachable before request: %w", err)
}
conn.Close() Type guard
var urlErr *url.Error
if errors.As(err, &urlErr) {
var netErr net.Error
if errors.As(urlErr.Err, &netErr) && netErr.Timeout() {
// transient — safe to retry
}
} Try / catch
resp, err := client.Do(req)
if err != nil {
var urlErr *url.Error
if errors.As(err, &urlErr) && isTransient(urlErr) {
return retryWithBackoff(req)
}
return nil, fmt.Errorf("请求网站首页失败: %w", err)
} Prevention
- Pre-check connectivity/DNS to the target domain before invoking discoverActionIDs.
- Configure proxy environment variables (HTTPS_PROXY) when the site requires one.
- Set a sane client Timeout and implement bounded retries with backoff.
- Keep the plugin's base URL/domain updated when the site migrates.
When it happens
Trigger: client.Do(req) returns a non-nil error inside findPotentialActionIDs (invoked via discoverActionIDs): network unreachable, DNS failure for the site domain, connection refused by the server/proxy, TLS certificate error, or request context timeout.
Common situations: The panyq site domain changed or is blocked by the user's firewall/GFW; the machine has no internet access; a corporate proxy is required but not configured; the site temporarily went offline; DNS pollution returning NXDOMAIN.
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/dc7b81fc53deea52.
Report an issue: GitHub.
Appendix: source
Thrown at plugin/panyq/panyq.go:661
return finalIDs, nil
}
// findPotentialActionIDs 从网站获取潜在的Action ID
func (p *PanyqPlugin) findPotentialActionIDs(client *http.Client) ([]string, error) {
// 请求网站首页
req, err := http.NewRequest("GET", BaseURL, nil)
if err != nil {
return nil, fmt.Errorf("创建请求失败: %w", err)
}
// 只保留指定的请求头
// req.Header.Set("sec-ch-ua", `"Not)A;Brand";v="8", "Chromium";v="138", "Google Chrome";v="138"`)
req.Header.Set("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36")
// 发送请求
resp, err := client.Do(req)
if err != nil {
return nil, fmt.Errorf("请求网站首页失败: %w", err)
}
defer resp.Body.Close()
// 检查状态码
if resp.StatusCode != http.StatusOK {
// 读取响应体以获取服务器返回的具体错误信息
bodyBytes, err := io.ReadAll(resp.Body)
if err != nil {
// 如果连响应体都读取失败,则返回状态码错误并附上读取错误
return nil, fmt.Errorf("请求失败,状态码: %d,且读取响应体错误: %v", resp.StatusCode, err)
}
// 将更详细的状态信息 (如 "404 Not Found") 和响应体内容一起作为错误返回
return nil, fmt.Errorf("请求失败,状态: %s, 详情: %s", resp.Status, string(bodyBytes))
}
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, fmt.Errorf("读取响应失败: %w", err)View on GitHub (pinned to beaa561337)