fish2018/pansou · error
[ ] API 返回错误: (code: )
Error message
[%s] API 返回错误: %s (code: %d)
What it means
The Feikuai API uses an application-level code field; when the JSON decodes fine but apiResp.Code != 0, searchImpl treats it as a business-logic error, includes apiResp.Msg and the code, and falls back to HTML search. The HTTP layer succeeded but the API itself reported an error.
Solutions
- Read apiResp.Msg and the numeric code to determine the API-specific cause
- Check the upstream API docs for current success code convention
- Sanitize/validate the keyword before querying
- Fall back to searchWeb results as designed
Example fix
// before
if apiResp.Code != 0 {
return p.searchWeb(client, keyword, fmt.Errorf("[%s] API 返回错误: %s (code: %d)", p.Name(), apiResp.Msg, apiResp.Code))
}
// after
if apiResp.Code != 0 {
log.Printf("feikuai API business error code=%d msg=%s keyword=%q", apiResp.Code, apiResp.Msg, keyword)
return p.searchWeb(client, keyword, fmt.Errorf("[%s] API 返回错误: %s (code: %d)", p.Name(), apiResp.Msg, apiResp.Code))
} Defensive patterns
Strategy: fallback
Validate before calling
// validate keyword before calling the API
if strings.TrimSpace(keyword) == "" { return nil, fmt.Errorf("empty keyword") }
if len([]rune(keyword)) > 100 { return nil, fmt.Errorf("keyword too long") } Try / catch
results, err := plugin.Search(keyword)
if err != nil {
var apiErr *apiBusinessError // if exported
if errors.As(err, &apiErr) && apiErr.Code != 0 {
log.Printf("feikuai API rejected query: code=%d msg=%s", apiErr.Code, apiErr.Msg)
// rely on web-scrape fallback or other plugins
}
} Prevention
- Read and log apiResp.Msg — it usually names the exact problem
- Sanitize keywords (strip banned characters) before querying
- Keep an in-body success-code check up to date with the API contract
- Never treat HTTP 200 + code!=0 as success
When it happens
Trigger: apiResp.Code != 0 in the decoded FeikuaiAPIResponse — e.g. invalid query parameters, banned keyword, account/IP throttling reported in-body.
Common situations: Upstream API contract change redefining success codes, empty or malformed keyword triggering an in-body error, IP throttled by the service.
Related errors
AI-assisted analysis of fish2018/pansou@beaa561337 (2026-09-07).
Data as JSON: /api/errors/b872b8021d162bef.
Report an issue: GitHub.
Appendix: source
Thrown at plugin/feikuai/feikuai.go:149
// 检查状态码
if resp.StatusCode != 200 {
return p.searchWeb(client, keyword, fmt.Errorf("[%s] 搜索 API 返回状态码: %d", p.Name(), resp.StatusCode))
}
// 读取并解析JSON响应
body, err := io.ReadAll(resp.Body)
if err != nil {
return p.searchWeb(client, keyword, fmt.Errorf("[%s] 读取 API 响应失败: %w", p.Name(), err))
}
var apiResp FeikuaiAPIResponse
if err := json.Unmarshal(body, &apiResp); err != nil {
return p.searchWeb(client, keyword, fmt.Errorf("[%s] API JSON 解析失败: %w", p.Name(), err))
}
// 检查API响应状态
if apiResp.Code != 0 {
return p.searchWeb(client, keyword, fmt.Errorf("[%s] API 返回错误: %s (code: %d)", p.Name(), apiResp.Msg, apiResp.Code))
}
// 解析搜索结果
var results []model.SearchResult
for _, item := range apiResp.Items {
// 每个item可能包含多个种子
for _, torrent := range item.Torrents {
result := p.parseTorrent(keyword, item, torrent)
if result.Title != "" && len(result.Links) > 0 {
results = append(results, result)
}
}
}
// 使用关键词过滤结果
return plugin.FilterResultsByKeyword(results, keyword), nil
}
View on GitHub (pinned to beaa561337)