fish2018/pansou · error
解析响应失败
Error message
解析响应失败: %w
What it means
pan666 plugin fetchPage wraps json.Unmarshal failures of the search API response body with this Chinese message ('failed to parse response'). It means the upstream pan666 API returned a body that is not valid JSON (or not the expected Pan666Response shape). The plugin treats any non-decodable body as a hard failure and aborts the search.
Solutions
- Print/log the raw responseBody on failure to see what the upstream actually returned (HTML vs JSON).
- Verify the pan666 API endpoint is reachable in a browser or via curl; update the base URL if the site moved.
- Add browser-like headers (User-Agent, Referer, Cookie) to the request to bypass anti-bot pages.
- If the schema changed, update the Pan666Response struct fields to match the new JSON.
Example fix
// before
if err := json.Unmarshal(responseBody, &apiResp); err != nil {
return nil, false, fmt.Errorf("解析响应失败: %w", err)
}
// after
if err := json.Unmarshal(responseBody, &apiResp); err != nil {
return nil, false, fmt.Errorf("解析响应失败: %w (body: %.200s)", err, responseBody)
} Defensive patterns
Strategy: try-catch
Validate before calling
// pre-check before trusting the API
if len(responseBody) == 0 || responseBody[0] != '{' {
return nil, false, fmt.Errorf("non-JSON response: %.200s", responseBody)
} Type guard
func looksLikeJSON(b []byte) bool {
t := bytes.TrimSpace(b)
return len(t) > 0 && (t[0] == '{' || t[0] == '[')
} Try / catch
results, partial, err := plugin.FetchPage(keyword)
if err != nil {
var uerr *fmt.Errorf // or errors.As on wrapped json.UnmarshalTypeError
log.Printf("pan666 parse failed: %v", err)
return fallbackSearch(keyword)
} Prevention
- Log the raw response body on every parse failure to spot HTML/anti-bot pages early.
- Send browser-like User-Agent/Referer headers to avoid HTML interstitials.
- Monitor the upstream endpoint with a periodic smoke-test request.
- Keep Pan666Response fields tolerant (omitempty, pointers) to survive schema drift.
When it happens
Trigger: fetchPage receives an HTTP response whose body cannot be unmarshaled into Pan666Response: HTML error pages, Cloudflare/CAPTCHA interstitials, rate-limit text, empty bodies, or a changed upstream JSON schema.
Common situations: Upstream pan666 site is down or behind anti-bot protection; the plugin's User-Agent is blocked; the API endpoint changed its response format after a site update; a proxy/gateway returned a non-JSON error page.
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/e718cacafd16952c.
Report an issue: GitHub.
Appendix: source
Thrown at plugin/pan666/pan666.go:241
}
// 状态码检查
if resp.StatusCode != http.StatusOK {
if i == p.retries {
return nil, false, fmt.Errorf("API返回非200状态码: %d", resp.StatusCode)
}
time.Sleep(500 * time.Millisecond)
continue
}
// 请求成功,跳出重试循环
break
}
// 解析响应
var apiResp Pan666Response
if err := json.Unmarshal(responseBody, &apiResp); err != nil {
return nil, false, fmt.Errorf("解析响应失败: %w", err)
}
// 处理结果
results := make([]model.SearchResult, 0, len(apiResp.Data))
postMap := make(map[string]Pan666Post)
// 创建帖子ID到帖子内容的映射
for _, post := range apiResp.Included {
postMap[post.ID] = post
}
// 遍历搜索结果
for _, discussion := range apiResp.Data {
// 获取相关帖子
postID := discussion.Relationships.MostRelevantPost.Data.ID
post, ok := postMap[postID]
if !ok {
continueView on GitHub (pinned to beaa561337)