fish2018/pansou · error
请求失败,状态: , 详情
Error message
请求失败,状态: %s, 详情: %s
What it means
The homepage request returned a non-200 status code, and the response body was successfully read, so the function reports the full HTTP status line (e.g. "404 Not Found") together with the body contents. This is the primary diagnostic error for server-side rejections of the homepage request: 403/429 from anti-bot protection, 404/410 if the site restructured, 5xx if the origin is unhealthy.
Solutions
- Read the 详情 body: a Cloudflare challenge/HTML error page there tells you the request is being blocked — switch to a residential IP or solve the challenge.
- If 429, back off and retry with a delay; add client-side rate limiting before calling discoverActionIDs.
- If 404/410, update the plugin's configured base URL — the site likely restructured.
- If 5xx, wait and retry; it is a server-side problem, not a client bug.
- Send browser-like headers (already partially done) and verify the User-Agent isn't stale versus the WAF's expectations.
Defensive patterns
Strategy: try-catch
Type guard
func isRetryableStatus(code int) bool {
switch code {
case http.StatusTooManyRequests,
http.StatusBadGateway,
http.StatusServiceUnavailable,
http.StatusGatewayTimeout:
return true
}
return code >= 500
} Try / catch
err := discoverActionIDs(ctx)
if err != nil {
if strings.Contains(err.Error(), "状态: 429") || strings.Contains(err.Error(), "状态: 5") {
time.Sleep(backoff)
return discoverActionIDs(ctx)
}
if strings.Contains(err.Error(), "状态: 404") {
return fmt.Errorf("site layout changed; update base URL")
}
return err
} Prevention
- Rate-limit requests to the site and back off on 429.
- Use residential IPs / solve challenges when a WAF blocks datacenter IPs.
- Monitor the 详情 body in logs — it names the blocker (Cloudflare, nginx, etc.).
- Keep the site URL current to avoid 404/410 after redeployments.
When it happens
Trigger: client.Do succeeded in findPotentialActionIDs but resp.StatusCode != http.StatusOK (e.g. 403 from Cloudflare, 429 rate limit, 502/503 from origin) and io.ReadAll(resp.Body) succeeded.
Common situations: Cloudflare/WAF challenge page returned for datacenter IPs; rate limiting after repeated calls to discoverActionIDs; site deployed a new version changing routes so old homepage paths 404; origin server temporarily down returning 5xx.
Understand the failure class
Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.
Related errors
AI-assisted analysis of fish2018/pansou@beaa561337 (2026-09-07).
Data as JSON: /api/errors/2df4f6753eefda53.
Report an issue: GitHub.
Appendix: source
Thrown at plugin/panyq/panyq.go:674
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)
}
// 提取JS文件路径
jsRegex := regexp.MustCompile(`<script src="(/_next/static/[^"]+\.js)"`)
matches := jsRegex.FindAllStringSubmatch(string(body), -1)
if len(matches) == 0 {
return nil, fmt.Errorf("未找到JS文件")
}
// 收集所有潜在的Action ID
idSet := make(map[string]struct{})
idRegex := regexp.MustCompile(`["\']([a-f0-9]{40})["\']{1}`)View on GitHub (pinned to beaa561337)