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

  1. Read apiResp.Msg and the numeric code to determine the API-specific cause
  2. Check the upstream API docs for current success code convention
  3. Sanitize/validate the keyword before querying
  4. 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

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)