fish2018/pansou · error
[ ] suggest 响应解析失败
Error message
[%s] suggest 响应解析失败: %w
What it means
Raised in searchSuggest (plugin/qiwei/qiwei.go:210) when the suggest endpoint's response body cannot be parsed as the expected suggestResponse JSON (code/msg/list). The json unmarshal error is wrapped with %w. Typically the site returned HTML (error page, verification page not caught by isVerifyPage, CDN block page) instead of the AJAX JSON payload.
Solutions
- Log/print the first ~200 bytes of body on this error to see what was actually returned (HTML vs JSON) — that determines the fix.
- If it's an unrecognized block/verification page, extend isVerifyPage's regexes in qiwei.go to detect it so the verification flow runs instead.
- If the API response shape changed, update the suggestResponse struct fields/tags.
- Retry with a different keyword or later; transient HTML error pages clear once upstream recovers.
Example fix
// before (debugging aid inside searchSuggest)
if err := json.Unmarshal([]byte(body), &resp); err != nil {
return nil, fmt.Errorf("[%s] suggest 响应解析失败: %w", p.Name(), err)
}
// after
if err := json.Unmarshal([]byte(body), &resp); err != nil {
return nil, fmt.Errorf("[%s] suggest 响应解析失败: %w, body=%q", p.Name(), err, body[:min(200, len(body))])
} Defensive patterns
Strategy: validation
Validate before calling
// validate the body looks like the expected JSON before unmarshalling
trimmed := strings.TrimSpace(body)
if !strings.HasPrefix(trimmed, "{") {
return fmt.Errorf("non-JSON suggest response (likely HTML): %.100s", trimmed)
} Try / catch
var resp suggestResponse
if err := json.Unmarshal([]byte(body), &resp); err != nil {
log.Printf("qiwei suggest returned non-JSON body: %.200s", body)
return nil, fmt.Errorf("suggest parse failed: %w", err) // host loop will try next mirror
} Prevention
- Log response bodies on parse failure to distinguish HTML block pages from format changes
- Keep isVerifyPage regexes up to date so HTML challenges route to the verification flow, not the JSON parser
- Pin keyword encoding via url.QueryEscape (already done) to avoid malformed request URLs
When it happens
Trigger: json.Unmarshal([]byte(body), &resp) returns an error after a successful fetchBody of /index.php/ajax/suggest?mid=1&limit=100&wd=<keyword> — i.e. HTTP succeeded but the body is not the expected JSON object.
Common situations: Site is behind a CDN serving an HTML challenge/error page that isVerifyPage's huadong regex doesn't recognize; keyword edge cases hitting a non-AJAX fallback page; the site changed its suggest API response format; server returned an HTML 5xx error page with status 200.
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/a7bec1a1b92022c4.
Report an issue: GitHub.
Appendix: source
Thrown at plugin/qiwei/qiwei.go:210
if err != nil {
return nil, err
}
if isVerifyPage(body) {
if err := p.solveVerification(client, searchURL, body); err != nil {
return nil, fmt.Errorf("[%s] 搜索验证失败: %w", p.Name(), err)
}
body, err = p.fetchBody(client, searchURL, host+"/", searchTimeout)
if err != nil {
return nil, err
}
if isVerifyPage(body) {
return nil, fmt.Errorf("[%s] 命中验证页: %s", p.Name(), host)
}
}
var resp suggestResponse
if err := json.Unmarshal([]byte(body), &resp); err != nil {
return nil, fmt.Errorf("[%s] suggest 响应解析失败: %w", p.Name(), err)
}
if resp.Code != 1 && len(resp.List) == 0 {
return nil, fmt.Errorf("[%s] suggest 响应异常: host=%s code=%d msg=%s", p.Name(), host, resp.Code, resp.Msg)
}
return resp.List, nil
}
func (p *QiweiPlugin) enrichResults(client *http.Client, host string, items []suggestItem, forceRefresh bool) []model.SearchResult {
results := make([]model.SearchResult, len(items))
var wg sync.WaitGroup
sem := make(chan struct{}, maxConcurrent)
for i, item := range items {
wg.Add(1)
go func(idx int, it suggestItem) {
defer wg.Done()View on GitHub (pinned to beaa561337)