fish2018/pansou · error
解析登录响应失败
Error message
解析登录响应失败: %w
What it means
The login POST returned HTTP 200 but the body could not be parsed as a LoginResponse JSON object. This usually means the server replied with HTML (error page, captcha page, or redirect) instead of the expected JSON.
Solutions
- Log the first bytes of respBody to identify what was actually returned
- Verify the login endpoint URL against the current site (open dev tools, re-capture the request)
- Update the LoginResponse struct if the JSON schema changed
- Handle captcha/verification requirements if present in the HTML
Example fix
// before
var loginResp LoginResponse
if err := json.Unmarshal(respBody, &loginResp); err != nil {
return "", nil, fmt.Errorf("解析登录响应失败: %w", err)
}
// after
var loginResp LoginResponse
if err := json.Unmarshal(respBody, &loginResp); err != nil {
return "", nil, fmt.Errorf("解析登录响应失败: %w; body=%.200s", err, string(respBody))
} Defensive patterns
Strategy: validation
Validate before calling
ct := resp.Header.Get("Content-Type")
if !strings.Contains(ct, "application/json") {
return fmt.Errorf("login returned non-JSON: %s", ct)
} Try / catch
if err := json.Unmarshal(respBody, &loginResp); err != nil {
log.Printf("login body: %.200s", string(respBody))
return fmt.Errorf("解析登录响应失败: %w", err)
} Prevention
- Check Content-Type before unmarshaling the login response
- Keep the login endpoint URL in sync with the live site
- Log response body snippets on parse failure
When it happens
Trigger: json.Unmarshal(respBody, &loginResp) fails because the login endpoint returned HTML or malformed/non-JSON content despite a 200 status.
Common situations: Site added captcha or changed the login endpoint to return HTML; WAF interstitial served with status 200; endpoint moved and an HTML 404 page was served with 200 via SPA fallback.
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/bf8763a89ea8a223.
Report an issue: GitHub.
Appendix: source
Thrown at plugin/panlian/panlian.go:1127
resp, err = client.Do(req)
if err != nil {
cancel()
return "", nil, err
}
defer resp.Body.Close()
respBody, err := io.ReadAll(resp.Body)
cancel()
if err != nil {
return "", nil, err
}
if resp.StatusCode != http.StatusOK {
return "", nil, fmt.Errorf("登录请求失败: HTTP %d", resp.StatusCode)
}
var loginResp LoginResponse
if err := json.Unmarshal(respBody, &loginResp); err != nil {
return "", nil, fmt.Errorf("解析登录响应失败: %w", err)
}
if !loginResp.Success {
return "", nil, errors.New(strings.TrimSpace(loginResp.Message))
}
cookieString := cookiesToString(jar.Cookies(baseURL))
if cookieString == "" {
return "", nil, fmt.Errorf("登录成功但未获取到有效 Cookie")
}
return cookieString, &loginResp, nil
}
func (p *PanlianPlugin) reloginUser(user *User) error {
password, err := p.decryptPassword(user.EncryptedPassword)
if err != nil {
return err
}View on GitHub (pinned to beaa561337)