fish2018/pansou · error

[ ] 获取首页失败

Error message

[%s] 获取首页失败: %w

What it means

When the first fetchFirstPage fails for any reason other than a 404, doSearch returns this wrapped error immediately without attempting a buildId refresh. It covers all non-404 failures of the initial search-API call.

Solutions

  1. Read the wrapped cause: 429/5xx → back off and retry later; connection errors → check network/proxy/DNS.
  2. Reduce request frequency to avoid rate limiting.
  3. Verify the upstream search endpoint is reachable from this host (curl the same URL).
  4. A 404 would have triggered a buildId refresh automatically; for other statuses handle retry logic in the caller.

Example fix

// before
results, err := plugin.Search(ctx, kw)
if err != nil {
    return err
}
// after
results, err := plugin.Search(ctx, kw)
if err != nil {
    if isRetryable(err) {
        time.Sleep(3 * time.Second)
        results, err = plugin.Search(ctx, kw)
    }
}
Defensive patterns

Strategy: retry

Validate before calling

// probe upstream health before searching
resp, err := http.Head("https://www.pansearch.me/")
if err != nil || resp.StatusCode >= 500 {
    // skip search, upstream unavailable
}

Try / catch

if err != nil && strings.Contains(err.Error(), "获取首页失败") {
    if strings.Contains(err.Error(), "context deadline exceeded") {
        // timeout: increase timeout and retry
    } else if strings.Contains(err.Error(), "429") {
        // rate limited: back off significantly
    }
}

Prevention

When it happens

Trigger: fetchFirstPage failed with a non-404 error: connection refused/reset, timeout, non-200 non-404 status (e.g. 500/503/429), or request-construction error.

Common situations: Upstream outage or maintenance (5xx), rate limiting (429), DNS/proxy misconfiguration, or the host being blocked by the upstream's anti-bot layer.

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/0f219976035fab3e. Report an issue: GitHub.

Appendix: source

Thrown at plugin/pansearch/pansearch.go:528

	}

	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 {
			return nil, fmt.Errorf("[%s] 获取首页失败: %w", p.Name(), err)
		}
	}

	allResults := append([]PanSearchItem(nil), firstPageResults...)
	pageCount := min((min(total, p.maxResults)+PageSize-1)/PageSize, MaxAPIPages)
	if pageCount > 1 {
		type pageResult struct {
			offset int
			items  []PanSearchItem
		}
		resultCh := make(chan pageResult, pageCount-1)
		sem := make(chan struct{}, min(p.maxConcurrent, pageCount-1))
		var wg sync.WaitGroup

		for page := 1; page < pageCount; page++ {
			offset := page * PageSize
			wg.Add(1)
			go func() {

View on GitHub (pinned to beaa561337)