fish2018/pansou · error

[ ] 请求返回状态码

Error message

[%s] 请求返回状态码: %d

What it means

Status error in ikantv's doSearch (plugin/ikantv/ikantv.go:90): the search endpoint responded after retries with a non-200 status. The request and headers were accepted at transport level but the site refused the search (rate limit, block, or endpoint change).

Solutions

  1. Check the logged status code: 403/429 imply blocking or rate limiting — reduce request frequency or change IP; 404/5xx imply site changes or upstream outage.
  2. Verify the plugin's search URL/path still matches the current ikantv API and update it if the site changed.
  3. Ensure the User-Agent/Referer headers still pass the site's bot checks.
  4. Retry later if the status is 5xx — it is usually a transient upstream problem.

Example fix

// before
if resp.StatusCode != http.StatusOK {
	return nil, fmt.Errorf("[%s] 请求返回状态码: %d", p.Name(), resp.StatusCode)
}
// after
if resp.StatusCode != http.StatusOK {
	bodySnippet, _ := io.ReadAll(io.LimitReader(resp.Body, 500))
	return nil, fmt.Errorf("[%s] 请求返回状态码: %d, body: %s", p.Name(), resp.StatusCode, string(bodySnippet))
}
Defensive patterns

Strategy: retry

Validate before calling

// pre-flight: does the upstream still serve the search path?
resp, err := client.Head(searchURL)
if err == nil && (resp.StatusCode == 403 || resp.StatusCode == 429) {
	return fmt.Errorf("ikantv is blocking this client (HTTP %d) — adjust rate/IP before searching", resp.StatusCode)
}

Try / catch

results, err := p.doSearch(ctx, keyword)
if err != nil {
	var statusErr *statusCodeError // if you wrap statuses in a typed error
	if errors.As(err, &statusErr) {
		switch {
		case statusErr.Code == 429 || statusErr.Code == 403:
			// back off / change IP / slow down
		case statusErr.Code >= 500:
			// transient: retry later
		default:
			// likely site change: check path/headers
		}
	}
}

Prevention

When it happens

Trigger: resp.StatusCode != http.StatusOK: 403/429 from anti-bot or rate limiting, 404 because the search path changed, 5xx from upstream server errors.

Common situations: 默认 Referer 失效触发防盗链;服务端 5xx。

Understand the failure class

Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.

Related errors


AI-assisted analysis of fish2018/pansou@beaa561337 (2026-09-07). Data as JSON: /api/errors/7f5cb4f8a0b0ab13. Report an issue: GitHub.

Appendix: source

Thrown at plugin/ikantv/ikantv.go:90

	req, err := http.NewRequestWithContext(ctx, http.MethodGet, searchURL, nil)
	if err != nil {
		return nil, fmt.Errorf("[%s] 创建请求失败: %w", p.Name(), err)
	}

	req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36")
	req.Header.Set("Accept", "application/json, text/plain, */*")
	req.Header.Set("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8")
	req.Header.Set("Connection", "keep-alive")
	req.Header.Set("Referer", defaultReferer)

	resp, err := p.doRequestWithRetry(req, client)
	if err != nil {
		return nil, fmt.Errorf("[%s] 搜索请求失败: %w", p.Name(), err)
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("[%s] 请求返回状态码: %d", p.Name(), resp.StatusCode)
	}

	body, err := io.ReadAll(resp.Body)
	if err != nil {
		return nil, fmt.Errorf("[%s] 读取响应失败: %w", p.Name(), err)
	}

	var apiResp apiResponse
	if err := json.Unmarshal(body, &apiResp); err != nil {
		return nil, fmt.Errorf("[%s] JSON解析失败: %w", p.Name(), err)
	}
	if apiResp.Code != 0 {
		return nil, fmt.Errorf("[%s] API错误: %s", p.Name(), apiResp.Message)
	}

	results := convertResults(apiResp.Data)
	return plugin.FilterResultsByKeyword(results, keyword), nil
}

View on GitHub (pinned to beaa561337)