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

  1. Log the item ID and raw payload when this fires to confirm whether it's dead content or an auth problem
  2. Refresh the session and retry the detail fetch once before giving up
  3. Skip and continue (current behavior) is correct for dead resources; surface a metric instead of failing the whole search
  4. Verify the detail URL path still matches the current site API
  5. 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

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)