fish2018/pansou · warning
rate limited
Error message
rate limited
What it means
The yuhuage plugin tracks a rateLimited flag set when a previous request received HTTP 429. While that flag is set (60 seconds), searchImpl short-circuits and returns "rate limited" without making any network request. It is a client-side circuit breaker, not the server's 429 itself.
Solutions
- Wait 60 seconds for the flag to reset, or reduce overall request rate to the plugin.
- Check debug logs ("当前处于限流状态,跳过搜索") to confirm the circuit breaker is active.
- Lower concurrency or add request pacing so the upstream never returns 429 in the first place.
- Treat this error as transient in the caller and skip/backoff rather than alerting.
Example fix
// before
if atomic.LoadInt32(&p.rateLimited) == 1 {
return nil, fmt.Errorf("rate limited")
}
// after
if atomic.LoadInt32(&p.rateLimited) == 1 {
time.Sleep(time.Until(rateLimitResetAt.Load()))
if atomic.LoadInt32(&p.rateLimited) == 1 {
return nil, fmt.Errorf("rate limited")
}
} Defensive patterns
Strategy: retry
Validate before calling
// no pre-call validation possible; the flag is internal.
// Instead, pace your calls:
if time.Since(lastYuhuageCall) < 2*time.Second {
time.Sleep(2*time.Second - time.Since(lastYuhuageCall))
} Try / catch
results, err := plugin.Search(keyword, ext)
if err != nil {
if err.Error() == "rate limited" {
time.Sleep(65 * time.Second)
results, err = plugin.Search(keyword, ext)
}
} Prevention
- Throttle search frequency so upstream never returns 429.
- Treat 'rate limited' as transient and cache/skip for the 60s window.
- Run a single shared instance rather than many clients hitting the same IP.
When it happens
Trigger: A Search/SearchWithResult call on YuhuagePlugin arrives while p.rateLimited == 1, i.e. within 60 seconds after any earlier request got a 429 from the upstream site.
Common situations: High search volume triggers the upstream site's rate limiting; many concurrent user searches fan out to this plugin; after one 429, all searches for the next minute fail fast with this error.
Related errors
AI-assisted analysis of fish2018/pansou@beaa561337 (2026-09-07).
Data as JSON: /api/errors/84e3e14476223404.
Report an issue: GitHub.
Appendix: source
Thrown at plugin/yuhuage/yuhuage.go:72
}
// SearchWithResult 执行搜索并返回包含IsFinal标记的结果
func (p *YuhuagePlugin) SearchWithResult(keyword string, ext map[string]interface{}) (model.PluginSearchResult, error) {
return p.AsyncSearchWithResult(keyword, p.searchImpl, p.MainCacheKey, ext)
}
// searchImpl 搜索实现方法
func (p *YuhuagePlugin) searchImpl(client *http.Client, keyword string, ext map[string]interface{}) ([]model.SearchResult, error) {
if p.debugMode {
log.Printf("[YUHUAGE] 开始搜索: %s", keyword)
}
// 检查限流状态
if atomic.LoadInt32(&p.rateLimited) == 1 {
if p.debugMode {
log.Printf("[YUHUAGE] 当前处于限流状态,跳过搜索")
}
return nil, fmt.Errorf("rate limited")
}
// 构建搜索URL
encodedQuery := url.QueryEscape(keyword)
searchURL := fmt.Sprintf("%s%s%s-%d-time.html", BaseURL, SearchPath, encodedQuery, 1)
// 创建带超时的上下文
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
// 创建请求对象
req, err := http.NewRequestWithContext(ctx, "GET", searchURL, nil)
if err != nil {
return nil, fmt.Errorf("[%s] 创建请求失败: %w", p.Name(), err)
}
// 设置请求头
req.Header.Set("User-Agent", UserAgent)View on GitHub (pinned to beaa561337)