fish2018/pansou · error
[ ] 搜索请求失败
Error message
[%s] 搜索请求失败: %w
What it means
lingjisp's fetchSearchItems failed to GET the getVideoList API endpoint after retries, wrapping the transport error from doLingjiGET. doLingjiGET already applies retries with exponential backoff, so this error means all attempts failed (DNS failure, timeout, connection refused, non-2xx/HTTP error propagation).
Solutions
- Verify the API base (lingjiAPIBase) domain is still alive with curl
- Check network/proxy configuration on the host
- Increase lingjiSearchTimeout and confirm lingjiMaxRetries is >1
- Update the API base URL to the current working domain
- Inspect the wrapped error to distinguish timeout vs connection refused vs HTTP status
Defensive patterns
Strategy: retry
Validate before calling
// Reachability pre-check before search
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
defer cancel()
req, _ := http.NewRequestWithContext(ctx, http.MethodGet, lingjiAPIBase, nil)
if _, err := http.DefaultClient.Do(req); err != nil {
return fmt.Errorf("灵集API不可达: %w", err)
} Try / catch
items, err := p.Search(ctx, keyword)
if err != nil {
if errors.Is(err, context.DeadlineExceeded) || isNetErr(err) {
time.Sleep(backoff)
items, err = p.Search(ctx, keyword) // doLingjiGET already retries internally
}
if err != nil {
return degradeGracefully(keyword)
}
} Prevention
- Set lingjiMaxRetries >= 3 with exponential backoff
- Use generous but bounded timeouts (lingjiSearchTimeout)
- Update the API base URL when the aggregator rotates domains
- Monitor DNS/network health on the host
When it happens
Trigger: doLingjiGET(client, lingjiAPIBase+"getVideoList?...", lingjiSearchTimeout) returned an error on every retry attempt — network unreachable, DNS failure, context deadline exceeded, or an HTTP status error was constructed inside doLingjiGET.
Common situations: API host blocked or offline; DNS resolution fails for the lingji API domain; client machine has no internet or a proxy misconfigured; lingjiSearchTimeout too short on slow networks; API domain rotated (these aggregator APIs change domains often).
Understand the failure class
Background: "API request failed": what wrapped HTTP errors from external APIs mean and how to find the real cause — this error's family across 29 libraries.
Related errors
AI-assisted analysis of fish2018/pansou@beaa561337 (2026-09-07).
Data as JSON: /api/errors/fef44077e7c2f2ce.
Report an issue: GitHub.
Appendix: source
Thrown at plugin/lingjisp/lingjisp.go:194
}(item)
}
wg.Wait()
return plugin.FilterResultsByKeyword(results, keyword), nil
}
func (p *LingjiPlugin) fetchSearchItems(client *http.Client, keyword string) ([]lingjiVideoItem, error) {
params := url.Values{}
params.Set("app_id", lingjiAppID)
params.Set("identity", lingjiIdentity)
params.Set("sb", keyword)
params.Set("page", "1")
params.Set("limit", "20")
apiURL := lingjiAPIBase + "getVideoList?" + params.Encode()
body, err := doLingjiGET(client, apiURL, lingjiSearchTimeout)
if err != nil {
return nil, fmt.Errorf("[%s] 搜索请求失败: %w", p.Name(), err)
}
var resp lingjiSearchResponse
if err := json.Unmarshal(body, &resp); err != nil {
return nil, fmt.Errorf("[%s] 解析搜索响应失败: %w", p.Name(), err)
}
if !resp.Success || resp.Code != http.StatusOK {
return nil, fmt.Errorf("[%s] 搜索接口返回异常: success=%v code=%d", p.Name(), resp.Success, resp.Code)
}
items := resp.Data.Data
if len(items) == 0 {
items = resp.Data.List
}
return dedupeLingjiItems(items), nil
}
func (p *LingjiPlugin) fetchDetail(client *http.Client, doubID int) (lingjiVideoItem, error) {View on GitHub (pinned to beaa561337)