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

  1. Log the first bytes of respBody to identify what was actually returned
  2. Verify the login endpoint URL against the current site (open dev tools, re-capture the request)
  3. Update the LoginResponse struct if the JSON schema changed
  4. 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

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)