fish2018/pansou · error
[ ] 获取访问挑战失败
Error message
[%s] 获取访问挑战失败
What it means
ensureSession requests a proof-of-work challenge from /traffic/session/challenge and validates the reply; this error means the challenge endpoint failed at the protocol level — JSON was malformed, success was false, or the challenge string was empty. Without a valid challenge the plugin cannot mint a nonce and obtain a session, so the search aborts.
Solutions
- Log the raw challengeBody on failure to see whether it's HTML (WAF) or an error JSON
- Compare the response shape against nsgameChallengeResponse and update the struct if the site changed fields
- Retry with backoff — challenge endpoints intermittently fail under load
- Test from a different IP; if another IP works, the current IP is rate-limited or banned
- Check whether nsthwj.cn moved the anti-bot endpoints and update the paths
Example fix
// before
if err := json.Unmarshal(challengeBody, &challenge); err != nil || !challenge.Success || challenge.Data.Challenge == "" {
return fmt.Errorf("[%s] 获取访问挑战失败", p.Name())
}
// after
if err := json.Unmarshal(challengeBody, &challenge); err != nil {
return fmt.Errorf("[%s] 获取访问挑战失败: 解析错误(响应开头: %.80q): %w", p.Name(), challengeBody, err)
} else if !challenge.Success || challenge.Data.Challenge == "" {
return fmt.Errorf("[%s] 获取访问挑战失败: success=%v, challenge=%q", p.Name(), challenge.Success, challenge.Data.Challenge)
} Defensive patterns
Strategy: retry
Try / catch
results, err := plugin.Search(keyword, ext)
if err != nil && strings.Contains(err.Error(), "获取访问挑战失败") {
time.Sleep(2 * time.Second)
results, err = plugin.Search(keyword, ext) // challenge endpoints are often transiently flaky
} Prevention
- Retry challenge acquisition with jittered backoff
- Log raw challenge responses to detect WAF/HTML interception immediately
- Update the challenge response struct whenever the site changes its anti-bot vendor
- Test from multiple IPs to distinguish bans from transient failures
When it happens
Trigger: Challenge endpoint returns HTML/empty body (json.Unmarshal fails), returns success=false (blocked/IP banned), or returns a JSON shape where data.challenge is missing/empty after a site API change.
Common situations: The site's anti-bot layer (e.g. Vaptcha-like traffic shield) changed its response format, the client IP is blacklisted, Cloudflare intercepts the challenge endpoint, or the site is under maintenance.
Related errors
AI-assisted analysis of fish2018/pansou@beaa561337 (2026-09-07).
Data as JSON: /api/errors/481db1f7a2ea73d5.
Report an issue: GitHub.
Appendix: source
Thrown at plugin/nsgame/nsgame.go:322
req.Header.Set("X-Client-Viewport", "1920x1080")
req.Header.Set("X-Client-Screen", "1920x1080@1")
}
func (p *NSGameAsyncPlugin) ensureSession(client *http.Client) error {
status, err := p.postSession(client, "/traffic/session/status", nil)
if err != nil {
return err
}
if status {
return nil
}
challengeBody, err := p.postSessionRaw(client, "/traffic/session/challenge", nil)
if err != nil {
return err
}
var challenge nsgameChallengeResponse
if err := json.Unmarshal(challengeBody, &challenge); err != nil || !challenge.Success || challenge.Data.Challenge == "" {
return fmt.Errorf("[%s] 获取访问挑战失败", p.Name())
}
nonce := solveChallenge(challenge.Data.Challenge, challenge.Data.DifficultyBits)
if nonce == "" {
return fmt.Errorf("[%s] 计算访问挑战失败", p.Name())
}
issueBody, _ := json.Marshal(map[string]string{"challenge": challenge.Data.Challenge, "nonce": nonce})
if _, err := p.postSessionRaw(client, "/traffic/session/issue", issueBody); err != nil {
return err
}
return nil
}
func (p *NSGameAsyncPlugin) postSession(client *http.Client, path string, body []byte) (bool, error) {
data, err := p.postSessionRaw(client, path, body)
if err != nil {
return false, err
}
var response nsgameSessionResponseView on GitHub (pinned to beaa561337)