fish2018/pansou · error

解析验证响应失败

Error message

解析验证响应失败: %w

What it means

Wrapped decode error in gying's challenge verification submission (plugin/gying/gying.go:1888): the verification endpoint answered 200 with a body that is not the expected challengeVerifyResponse JSON — typically another challenge page or an HTML error.

Solutions

  1. Log a snippet of respBody to see what was actually returned.
  2. Check resp.StatusCode alongside the body; non-200 usually means an HTML error page.
  3. Update cloudscraper / challenge parsing if the site changed its verify endpoint response.
  4. Retry; transient HTML interstitials can masquerade as parse failures.
Defensive patterns

Strategy: validation

Validate before calling

if !json.Valid(respBody) { return fmt.Errorf("non-JSON response (status=%d)", resp.StatusCode) }

Type guard

var probe map[string]any; if err := json.Unmarshal(respBody, &probe); err != nil || probe["success"] == nil { /* treat as HTML/error page */ }

Try / catch

if err != nil { if strings.Contains(err.Error(), "解析验证响应失败") { logBodySnippet(respBody); checkStatusCode(); } }

Prevention

When it happens

Trigger: submitChallengeVerification receives a 200 response whose body is not valid JSON matching challengeVerifyResponse (e.g. an HTML error page with a 200 status).

Common situations: 提交后触发新一轮反爬页面;验证接口结构变更。

Understand the failure class

Background: "failed to unmarshal" / json.Unmarshal errors: why parsing a response into a Go struct fails and how to fix it — this error's family across 23 libraries.

Related errors


AI-assisted analysis of fish2018/pansou@beaa561337 (2026-09-07). Data as JSON: /api/errors/ee47ae40c18f3329. Report an issue: GitHub.

Appendix: source

Thrown at plugin/gying/gying.go:1888

		return fmt.Errorf("提交验证失败: %w", err)
	}
	defer resp.Body.Close()

	if DebugLog {
		fmt.Printf("[Gying] Challenge提交完成: url=%s status=%d\n", requestURL, resp.StatusCode)
	}

	respBody, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return fmt.Errorf("读取验证响应失败: %w", err)
	}
	if isBotChallengePage(respBody) {
		return fmt.Errorf("机器人验证出现循环")
	}

	var verifyResp challengeVerifyResponse
	if err := json.Unmarshal(respBody, &verifyResp); err != nil {
		return fmt.Errorf("解析验证响应失败: %w", err)
	}
	if !verifyResp.Success {
		if verifyResp.Msg != "" {
			return fmt.Errorf("机器人验证失败: %s", verifyResp.Msg)
		}
		return fmt.Errorf("机器人验证失败")
	}

	if DebugLog {
		fmt.Printf("[Gying] Challenge验证成功: url=%s\n", requestURL)
	}

	return nil
}

func (p *GyingPlugin) requestWithChallengeRetry(scraper *cloudscraper.Scraper, method, requestURL, contentType, requestBody string) ([]byte, int, http.Header, error) {
	for attempt := 0; attempt < 2; attempt++ {
		var (

View on GitHub (pinned to beaa561337)