fish2018/pansou · error
[ ] 详情请求失败
Error message
[%s] 详情请求失败: %w
What it means
fetchDetail failed to GET the getVideoDetail endpoint for a given video id, wrapping the transport error from doLingjiGET (retries already exhausted). Mirrors the search failure path but for the detail API.
Solutions
- Test the exact getVideoDetail URL with curl to see whether the endpoint is reachable
- Check the wrapped error for timeout vs connection-refused vs HTTP status
- Increase lingjiDetailTimeout / confirm retry count
- Validate the doubID before calling fetchDetail to avoid requests the API cannot serve
- Update lingjiAPIBase if the domain rotated
Defensive patterns
Strategy: retry
Validate before calling
// Validate the id and endpoint reachability before detail fetch
if doubID <= 0 {
return fmt.Errorf("非法详情ID: %d", doubID)
}
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
defer cancel()
if !isEndpointReachable(ctx, lingjiAPIBase) {
return fmt.Errorf("灵集API不可达")
} Try / catch
item, err := fetchDetail(doubID)
if err != nil {
if errors.Is(err, context.DeadlineExceeded) || isNetErr(err) {
if item, rerr := fetchDetail(doubID); rerr == nil {
return item, nil
}
}
return emptyItem, err
} Prevention
- Validate ids before requesting details
- Rely on doLingjiGET retries; keep timeouts sane
- Check the wrapped cause (timeout vs refused vs HTTP status) in logs
- Update the base URL when the domain rotates
When it happens
Trigger: doLingjiGET(client, lingjiAPIBase+"getVideoDetail?identity=...&id=<doubID>", lingjiDetailTimeout) failed on all attempts — network outage, DNS failure, timeout, or HTTP-level error raised inside doLingjiGET.
Common situations: API domain offline or blocked; host network issues; lingjiDetailTimeout too small; invalid id causing server to hang or connection reset; proxy misconfiguration.
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/c4eaacd463322476.
Report an issue: GitHub.
Appendix: source
Thrown at plugin/lingjisp/lingjisp.go:221
}
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) {
params := url.Values{}
params.Set("app_id", lingjiAppID)
params.Set("identity", lingjiIdentity)
params.Set("id", fmt.Sprintf("%d", doubID))
apiURL := lingjiAPIBase + "getVideoDetail?" + params.Encode()
body, err := doLingjiGET(client, apiURL, lingjiDetailTimeout)
if err != nil {
return lingjiVideoItem{}, fmt.Errorf("[%s] 详情请求失败: %w", p.Name(), err)
}
var resp lingjiDetailResponse
if err := json.Unmarshal(body, &resp); err != nil {
return lingjiVideoItem{}, fmt.Errorf("[%s] 解析详情响应失败: %w", p.Name(), err)
}
if !resp.Success || resp.Code != http.StatusOK {
return lingjiVideoItem{}, fmt.Errorf("[%s] 详情接口返回异常: success=%v code=%d", p.Name(), resp.Success, resp.Code)
}
return resp.Data, nil
}
func doLingjiGET(client *http.Client, requestURL string, timeout time.Duration) ([]byte, error) {
var lastErr error
for attempt := 0; attempt < lingjiMaxRetries; attempt++ {
ctx, cancel := context.WithTimeout(context.Background(), timeout)
req, err := http.NewRequestWithContext(ctx, http.MethodGet, requestURL, nil)View on GitHub (pinned to beaa561337)