fish2018/pansou · error

getKey id= code= msg=

Error message

getKey id=%d code=%d msg=%s

What it means

This error is returned by YingsoPlugin.resolveItem when the /getKey endpoint returns a non-200 code in its envelope OR returns an empty/whitespace data field, meaning the share key for a specific search result could not be obtained. It embeds the item ID plus the API's code and msg so the failing resource can be identified.

Solutions

  1. Log item.ID with the API code/msg to confirm whether it is per-resource (deleted/private) or global (auth/rate limit).
  2. Re-fetch bootstrap config (url_version, user_id) via fetchConfig and retry resolveItem if code indicates auth/parameter issues.
  3. Apply a small backoff/retry for transient codes; individual item failures are already tolerated by searchImpl unless ALL items fail.
  4. Treat empty data with code 200 as 'resource unavailable' and skip the item rather than surfacing it as a hard failure.
  5. If many items fail simultaneously, suspect the Yingso API changed its getKey contract and update the payload/encryption accordingly.

Example fix

// before
if response.Code != http.StatusOK || strings.TrimSpace(response.Data) == "" {
	return model.SearchResult{}, fmt.Errorf("getKey id=%d code=%d msg=%s", item.ID, response.Code, response.Msg)
}
// after
if response.Code != http.StatusOK || strings.TrimSpace(response.Data) == "" {
	if isTransientCode(response.Code) {
		time.Sleep(200 * time.Millisecond)
		return p.resolveItem(ctx, client, config, item)
	}
	return model.SearchResult{}, fmt.Errorf("getKey id=%d code=%d msg=%s", item.ID, response.Code, response.Msg)
}
Defensive patterns

Strategy: try-catch

Try / catch

result, err := resolveItem(ctx, client, config, item)
if err != nil {
	if strings.Contains(err.Error(), "getKey") {
		// per-item failure: skip this item, continue with others
		log.Printf("skipping item (%v)", err)
		return nil
	}
	return err
}

Prevention

When it happens

Trigger: POST {apiBaseURL}/{url_version}/getKey with {id, userId} returns apiEnvelope[string] where code != 200 or strings.TrimSpace(response.Data) == "" — typically the resource was removed, is private, has no share key, or the encrypted payload was rejected.

Common situations: Search results are stale and the underlying netdisk share has been deleted or taken down; the API withholds keys for sensitive resources; heavy concurrency (up to 8 parallel getKey calls) triggers per-item rate limiting; user_id from bootstrap config became invalid.

Related errors


AI-assisted analysis of fish2018/pansou@beaa561337 (2026-09-07). Data as JSON: /api/errors/495afd59ee5df6b6. Report an issue: GitHub.

Appendix: source

Thrown at plugin/yingso/yingso.go:248

		return nil, fmt.Errorf("[%s] 搜索接口异常: code=%d msg=%s", p.Name(), response.Code, response.Msg)
	}
	return response.Data, nil
}

func (p *YingsoPlugin) resolveItem(ctx context.Context, client *http.Client, config apiConfig, item searchItem) (model.SearchResult, error) {
	payload := getKeyPayload{ID: item.ID, UserID: config.UserID}
	encrypted, err := encryptPayload(payload, config)
	if err != nil {
		return model.SearchResult{}, err
	}

	var response apiEnvelope[string]
	endpoint := fmt.Sprintf("%s/%s/getKey", p.apiBaseURL, url.PathEscape(config.URLVersion))
	if err := p.requestJSON(ctx, client, http.MethodPost, endpoint, encrypted, &response); err != nil {
		return model.SearchResult{}, err
	}
	if response.Code != http.StatusOK || strings.TrimSpace(response.Data) == "" {
		return model.SearchResult{}, fmt.Errorf("getKey id=%d code=%d msg=%s", item.ID, response.Code, response.Msg)
	}

	linkType, linkURL, password := buildLink(item.Root, response.Data)
	if linkURL == "" {
		return model.SearchResult{}, fmt.Errorf("不支持的网盘类型 root=%d id=%d", item.Root, item.ID)
	}

	title := cleanText(item.Title)
	if title == "" {
		title = fmt.Sprintf("影搜资源 %d", item.ID)
	}
	id := fmt.Sprintf("%s-%d", pluginName, item.ID)
	now := time.Now()
	return model.SearchResult{
		MessageID: id,
		UniqueID:  id,
		Channel:   "",
		Datetime:  now,

View on GitHub (pinned to beaa561337)