fish2018/pansou · error

[ ] 刷新 buildId 后获取首页失败

Error message

[%s] 刷新 buildId 后获取首页失败: %w

What it means

Recovery-path error in pansearch's doSearch (plugin/pansearch/pansearch.go:525): after a 404 triggered a buildId cache reset, re-fetching the site's base URL/buildId failed again, so the fallback recovery itself failed and the search aborts.

Solutions

  1. Check the wrapped error to determine whether the retry failed with 404 again or a network/timeout error.
  2. If 404 persists, the search API URL scheme may have changed — verify against the current upstream frontend requests.
  3. Retry later with backoff; the issue may be transient upstream instability.
  4. Capture the request URL used and compare it with the upstream site's live API calls.
Defensive patterns

Strategy: retry

Try / catch

if err != nil && strings.Contains(err.Error(), "刷新 buildId 后获取首页失败") {
    // even the retry failed — treat as upstream outage
    return err
}

Prevention

When it happens

Trigger: buildId was refreshed but the retried fetchFirstPage still failed — network error, timeout, another 404, or another non-200 status from the search API.

Common situations: 站点频繁重新部署导致 buildId 连续变化;getBaseURL 解析页面失败。

Understand the failure class

Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.

Related errors


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

Appendix: source

Thrown at plugin/pansearch/pansearch.go:525

	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 {
			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++ {

View on GitHub (pinned to beaa561337)