fish2018/pansou · error
[ ] 获取API基础URL失败
Error message
[%s] 获取API基础URL失败: %w
What it means
doSearch wraps any error from getBaseURL (buildId resolution) with this message. It signals the plugin could not determine the API base URL/buildId, and the wrapped error (non-200 status, body read failure, or buildId not found) is the real cause.
Solutions
- Inspect the wrapped cause (%w) — fix the underlying buildId fetch issue first.
- Retry after a delay; a successful buildId fetch will be cached and subsequent calls succeed.
- Check upstream availability and any rate limiting/blocking (429/403).
- Clear the buildId cache if a stale value is suspected and retry.
Example fix
// before
baseURL, err := p.getBaseURL(client)
// after
baseURL, err := p.getBaseURL(client)
if err != nil {
log.Printf("getBaseURL failed: %v; will retry once", err)
time.Sleep(time.Second)
baseURL, err = p.getBaseURL(client)
} Defensive patterns
Strategy: try-catch
Try / catch
if err != nil && strings.Contains(err.Error(), "获取API基础URL失败") {
var wrapped error = errors.Unwrap(err) // inspect root cause
log.Printf("buildId/baseURL resolution failed: %v", wrapped)
// schedule a retry with backoff
} Prevention
- Check the wrapped cause to distinguish upstream outage from markup changes
- Retry with exponential backoff rather than tight loops
- Alert on repeated occurrences — indicates the upstream is blocking or redesigned
When it happens
Trigger: Any getBuildId failure — upstream non-200 response, body read error, or buildId extraction failure with no cache — surfacing through doSearch.
Common situations: First-ever call with no cached buildId while the upstream is down/rate-limiting, upstream markup changed, or network egress blocked from the host.
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/5cdef9ad7d0e2a2c.
Report an issue: GitHub.
Appendix: source
Thrown at plugin/pansearch/pansearch.go:509
return result.Results, nil
}
// SearchWithResult 执行搜索并返回包含IsFinal标记的结果
func (p *PanSearchAsyncPlugin) SearchWithResult(keyword string, ext map[string]interface{}) (model.PluginSearchResult, error) {
return p.AsyncSearchWithResult(keyword, p.doSearch, p.MainCacheKey, ext)
}
// doSearch 执行具体的搜索逻辑
func (p *PanSearchAsyncPlugin) doSearch(client *http.Client, keyword string, ext map[string]interface{}) ([]model.SearchResult, error) {
keyword = strings.TrimSpace(keyword)
if keyword == "" {
return nil, fmt.Errorf("[%s] 关键词不能为空", p.Name())
}
client = p.requestClient(client)
baseURL, err := p.getBaseURL(client)
if err != nil {
return nil, fmt.Errorf("[%s] 获取API基础URL失败: %w", p.Name(), err)
}
firstPageResults, total, err := p.fetchFirstPage(keyword, baseURL, client)
if err != nil {
if strings.Contains(err.Error(), "404") || strings.Contains(err.Error(), "Not Found") {
buildIdMutex.Lock()
buildIdCache = ""
buildIdCacheTime = time.Time{}
buildIdMutex.Unlock()
baseURL, err = p.getBaseURL(client)
if err != nil {
return nil, fmt.Errorf("[%s] 刷新 buildId 失败: %w", p.Name(), err)
}
firstPageResults, total, err = p.fetchFirstPage(keyword, baseURL, client)
if err != nil {
return nil, fmt.Errorf("[%s] 刷新 buildId 后获取首页失败: %w", p.Name(), err)
}
} else {View on GitHub (pinned to beaa561337)