fish2018/pansou · error
[ ] 搜索接口返回状态码
Error message
[%s] 搜索接口返回状态码: %d
What it means
This error is returned by MiosouPlugin.searchImpl when the search API responds with a status code other than 200 (and the response is not detected as an Anubis gate page). The plugin closes the body, cancels the context, and fails fast with the numeric code embedded rather than parsing a non-200 body.
Solutions
- Read the status code from the message; 429/403 means slow down or change IP, 5xx means retry later
- Check the API endpoint in a browser/curl to see if it still exists (404) or is protected (403)
- Reduce search frequency / add jitter between searches to avoid rate limiting
- Keep headers (setHeaders with Accept: text/event-stream) consistent with what the API expects
Example fix
// caller-side classification
err := search(...)
if strings.Contains(err.Error(), "状态码: 429") {
time.Sleep(2 * time.Minute)
} else if strings.Contains(err.Error(), "状态码: 5") {
// transient upstream error, retry with backoff
} Defensive patterns
Strategy: retry
Validate before calling
// Go: probe the endpoint before real searches
resp, err := http.Get(apiBaseURL + "/search?keyword=test")
if err == nil {
io.Copy(io.Discard, io.LimitReader(resp.Body, 1<<10))
resp.Body.Close()
if resp.StatusCode != http.StatusOK {
// endpoint degraded/blocked; skip batch
}
} Type guard
func isStatusErr(err error) bool {
return err != nil && strings.Contains(err.Error(), "搜索接口返回状态码")
} Try / catch
if err != nil {
if isStatusErr(err) {
if strings.Contains(err.Error(), "429") {
time.Sleep(2 * time.Minute) // rate limited: back off
}
return nil, err
}
} Prevention
- Throttle search frequency below the site's rate limit
- Reuse one client so gate cookies persist
- Keep Accept: text/event-stream headers intact
- Alert on 404 to catch endpoint removals after site updates
When it happens
Trigger: searchImpl's client.Do succeeds, isAnubisGateResponse returns false, but resp.StatusCode is e.g. 403 (blocked), 429 (rate limited), 500/502/503 (upstream error) on both allowed attempts' first pass — the loop does not retry non-200 non-gate responses.
Common situations: Server-side rate limiting after frequent searches; IP blocked by the site's firewall; temporary upstream outage (502/503); API endpoint removed or moved (404) after a site update.
Related errors
AI-assisted analysis of fish2018/pansou@beaa561337 (2026-09-07).
Data as JSON: /api/errors/2cb069d63e8f7a65.
Report an issue: GitHub.
Appendix: source
Thrown at plugin/miosou/miosou.go:118
setHeaders(req, "text/event-stream")
resp, err := p.client.Do(req)
if err != nil {
cancel()
return nil, fmt.Errorf("[%s] 搜索请求失败: %w", p.Name(), err)
}
if isAnubisGateResponse(resp) {
resp.Body.Close()
cancel()
p.invalidateGate()
if err := p.ensureGate(); err != nil {
return nil, err
}
continue
}
if resp.StatusCode != http.StatusOK {
resp.Body.Close()
cancel()
return nil, fmt.Errorf("[%s] 搜索接口返回状态码: %d", p.Name(), resp.StatusCode)
}
groups, err := parseSearchStream(resp.Body)
resp.Body.Close()
if err != nil {
cancel()
return nil, fmt.Errorf("[%s] 解析搜索流失败: %w", p.Name(), err)
}
results := p.convertGroups(ctx, groups, keyword)
cancel()
return results, nil
}
return nil, fmt.Errorf("[%s] 人机验证会话失效", p.Name())
}
func (p *MiosouPlugin) ensureGate() error {
p.gateMu.Lock()
defer p.gateMu.Unlock()
if p.gateReady {View on GitHub (pinned to beaa561337)