fish2018/pansou · warning
详情接口返回无效数据
Error message
详情接口返回无效数据
What it means
fetchDetail decoded the detail API response but it is semantically invalid: payload.Success is false or payload.Data.ID is 0, so no usable detail record exists. The plugin returns this sentinel error; the caller (the goroutine in searchImpl) silently drops the item, so the resource is simply missing from results.
Solutions
- Log the item ID and raw payload when this fires to confirm whether it's dead content or an auth problem
- Refresh the session and retry the detail fetch once before giving up
- Skip and continue (current behavior) is correct for dead resources; surface a metric instead of failing the whole search
- Verify the detail URL path still matches the current site API
- Check if the API now nests data differently so Data.ID is always 0 due to a schema change
Example fix
// before
if !payload.Success || payload.Data.ID == 0 {
return NSGameItem{}, fmt.Errorf("详情接口返回无效数据")
}
// after
if !payload.Success || payload.Data.ID == 0 {
return NSGameItem{}, fmt.Errorf("详情接口返回无效数据: id=%d, success=%v", itemID, payload.Success)
} Defensive patterns
Strategy: fallback
Try / catch
results, err := plugin.Search(keyword, ext)
// this error is swallowed per-item by the plugin; instead validate the result set
if err == nil && len(results) == 0 {
log.Warn("nsgame returned no usable detail records")
} Prevention
- Expect dead/private resources in any scraped index — drop them silently but count them
- Refresh the anti-bot session if detail failures spike suddenly
- Log item IDs on invalid detail payloads to distinguish dead links from auth issues
- Cross-check with a second source when detail data is missing
When it happens
Trigger: Detail endpoint returns success=false for a deleted/private resource, the item ID doesn't exist anymore, or the session is invalid so the detail API rejects the request while still returning JSON.
Common situations: Search index lists entries whose detail pages were removed (dead links), resource made private, or anti-bot session expired between the search call and the detail calls.
Understand the failure class
Background: "invalid response format", "malformed payload", "missing data field": when an API returns 200 but the response shape is wrong — this error's family across 23 libraries.
Related errors
AI-assisted analysis of fish2018/pansou@beaa561337 (2026-09-07).
Data as JSON: /api/errors/8ac8baf8bc35badb.
Report an issue: GitHub.
Appendix: source
Thrown at plugin/nsgame/nsgame.go:271
func (p *NSGameAsyncPlugin) fetchDetail(client *http.Client, id int) (NSGameItem, error) {
ctx, cancel := context.WithTimeout(context.Background(), defaultTimeout)
defer cancel()
req, err := http.NewRequestWithContext(ctx, http.MethodGet, fmt.Sprintf("%s/game/detail?id=%d", baseURL, id), nil)
if err != nil {
return NSGameItem{}, err
}
p.setRequestHeaders(req, "https://nsthwj.cn/")
resp, err := p.doRequestWithRetry(req, client)
if err != nil {
return NSGameItem{}, err
}
defer resp.Body.Close()
var payload NSGameDetailResponse
if err := stdjson.NewDecoder(resp.Body).Decode(&payload); err != nil {
return NSGameItem{}, err
}
if !payload.Success || payload.Data.ID == 0 {
return NSGameItem{}, fmt.Errorf("详情接口返回无效数据")
}
return payload.Data, nil
}
func newVisitorID() string {
b := make([]byte, 16)
if _, err := rand.Read(b); err != nil {
return fmt.Sprintf("%x-0000-4000-8000-%012d", md5.Sum([]byte(time.Now().String())), time.Now().UnixNano()%1e12)
}
b[6] = (b[6] & 0x0f) | 0x40
b[8] = (b[8] & 0x3f) | 0x80
buf := make([]byte, 36)
hex.Encode(buf[0:8], b[0:4])
buf[8] = '-'
hex.Encode(buf[9:13], b[4:6])
buf[13] = '-'
hex.Encode(buf[14:18], b[6:8])
buf[18] = '-'View on GitHub (pinned to beaa561337)