fish2018/pansou · error
获取搜索凭证失败
Error message
获取搜索凭证失败: %w
What it means
doSearch fails while obtaining search credentials after refreshing the Action ID: the wrapped error comes from p.getCredentials(keyword, actionID, client), which performs the site's credential API call. This means the plugin could not obtain a valid Sign/Hash/Sha credential even after one Action ID refresh retry. It aborts the search before any results are fetched.
Solutions
- Re-run the search to trigger Action ID re-discovery (cached IDs may be stale — clear the in-memory action ID cache or restart the plugin).
- Check DebugLog output to see the underlying wrapped error from getCredentials and confirm which HTTP status/parse failure occurred.
- Verify network connectivity to BaseURL from the host (curl the site homepage).
- Update the plugin to a version matching the current upstream site layout.
Example fix
// before
credentials, err = p.getCredentials(keyword, actionIDs[ActionIDKeys[0]], client)
if err != nil {
return nil, fmt.Errorf("获取搜索凭证失败: %w", err)
}
// after
credentials, err = p.getCredentials(keyword, actionIDs[ActionIDKeys[0]], client)
if err != nil {
p.invalidateActionIDCache() // drop possibly stale IDs before returning
return nil, fmt.Errorf("获取搜索凭证失败: %w", err)
} Defensive patterns
Strategy: try-catch
Validate before calling
if err := pingBaseURL(BaseURL); err != nil {
return fmt.Errorf("site unreachable, skipping panyq search: %w", err)
} Try / catch
results, err := plugin.Search(keyword)
if err != nil {
if strings.Contains(err.Error(), "获取搜索凭证失败") {
log.Printf("credential fetch failed (site may have changed): %v", err)
return fallbackResults(keyword) // use another source
}
return err
} Prevention
- Keep the plugin updated against upstream site changes
- Check site reachability before search
- Clear/rebuild the action ID cache after upstream deploys
- Log the wrapped cause (%w) for diagnosis
When it happens
Trigger: Calling doSearch (or the plugin search entry) when the credential endpoint returns an error — e.g. the site changed its credential API, the Action ID is stale/wrong, the upstream returns non-200, or the response JSON cannot be parsed.
Common situations: Upstream site updated its frontend/obfuscation so action IDs no longer match; network/firewall blocking the site; temporary 5xx from the target site; rate limiting.
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/7e4cdef8fbe31e7e.
Report an issue: GitHub.
Appendix: source
Thrown at plugin/panyq/panyq.go:223
actionIDs, err := p.getOrDiscoverActionIDs()
if err != nil {
// fmt.Println("panyq: failed to get Action IDs:", err)
return nil, fmt.Errorf("获取Action ID失败: %w", err)
}
// 步骤1: 获取搜索凭证
credentials, err := p.getCredentials(keyword, actionIDs[ActionIDKeys[0]], client)
if err != nil {
// 如果获取凭证失败,尝试刷新Action ID并重试
actionIDs, err = p.discoverActionIDs()
if err != nil {
return nil, fmt.Errorf("刷新Action ID失败: %w", err)
}
// 使用新的Action ID重试获取凭证
credentials, err = p.getCredentials(keyword, actionIDs[ActionIDKeys[0]], client)
if err != nil {
return nil, fmt.Errorf("获取搜索凭证失败: %w", err)
}
}
// 步骤2: 获取第一页搜索结果列表
hits, maxPageNum, err := p.getSearchResults(credentials.Sign, 1, client)
if err != nil {
return nil, fmt.Errorf("获取搜索结果失败: %w", err)
}
if len(hits) == 0 {
if DebugLog {
fmt.Println("panyq: no results found for", keyword)
}
return []model.SearchResult{}, nil
}
// 如果有多页结果,并发获取其他页的数据
if maxPageNum > 1 {View on GitHub (pinned to beaa561337)