fish2018/pansou · error
[ ] 详情接口返回异常: success= code=
Error message
[%s] 详情接口返回异常: success=%v code=%d
What it means
The getVideoDetail JSON parsed but the envelope check failed: resp.Success was false or resp.Code was not 200, so fetchDetail aborts reporting both values. The upstream API explicitly signaled an error for this detail request.
Solutions
- Include the API's message field in the log to learn the exact upstream reason
- Validate the doubID exists (via search results) before fetching details
- Verify lingjiIdentity and other params against the current API docs
- Add backoff for code values indicating throttling
- Update the plugin if the API changed status-code semantics
Defensive patterns
Strategy: try-catch
Validate before calling
// Only query ids that came from a successful search response
if doubID <= 0 || !idFromSearchResults(doubID) {
return lingjiVideoItem{}, fmt.Errorf("跳过未知详情ID: %d", doubID)
} Try / catch
item, err := fetchDetail(doubID)
var apiErr *LingjiAPIError
if errors.As(err, &apiErr) {
switch {
case apiErr.Code == http.StatusNotFound:
return emptyItem, nil // record genuinely not found upstream
case isThrottleCode(apiErr.Code):
time.Sleep(backoff)
return fetchDetail(doubID)
default:
return emptyItem, err
}
} Prevention
- Treat code!=200 with the API's message field for root cause
- Expect record-not-found for stale ids and skip gracefully
- Back off on throttling codes instead of hammering
- Re-verify lingjiIdentity after API updates
When it happens
Trigger: Valid JSON from getVideoDetail whose success=false or code!=200 — typically id not found in the API's database, invalid/missing identity parameter, or upstream-side rate limiting/authorization failure.
Common situations: Requested douban id doesn't exist upstream (record-not-found from the API); lingjiIdentity stale after API update; API throttles bursts of detail lookups during scraping; account/token requirements introduced by an API version change.
Related errors
AI-assisted analysis of fish2018/pansou@beaa561337 (2026-09-07).
Data as JSON: /api/errors/6e078956f26f4e31.
Report an issue: GitHub.
Appendix: source
Thrown at plugin/lingjisp/lingjisp.go:229
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)
if err != nil {
cancel()
return nil, err
}
req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 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")View on GitHub (pinned to beaa561337)