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

  1. Log the raw challengeBody on failure to see whether it's HTML (WAF) or an error JSON
  2. Compare the response shape against nsgameChallengeResponse and update the struct if the site changed fields
  3. Retry with backoff — challenge endpoints intermittently fail under load
  4. Test from a different IP; if another IP works, the current IP is rate-limited or banned
  5. 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

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 nsgameSessionResponse

View on GitHub (pinned to beaa561337)