fish2018/pansou · warning
[ ] 429限流,
Error message
[%s] 429限流,%s
What it means
doRequestWithRateLimitRetry returns '[javdb] 429限流,%s' (429 rate limited) when the server responds 429 and the plugin either has MaxRetryOnRateLimit == 0 (no retries allowed) or has already exhausted the allowed retry attempts. It also sets the plugin's atomic rateLimited flag so the caller knows the source is throttled.
Solutions
- Increase MaxRetryOnRateLimit or remove a 0 setting that disables retries
- Add per-request delay/rate limiting between detail-page fetches
- Respect any Retry-After header from the 429 response before retrying
- Back off globally when the rateLimited flag is set (skip javdb for a cooldown period)
- Reduce concurrency/parallel requests to javdb
Example fix
// before
for _, link := range links {
fetchDetail(link)
}
// after
for _, link := range links {
fetchDetail(link)
time.Sleep(requestInterval)
} Defensive patterns
Strategy: fallback
Validate before calling
// Go: throttle before issuing detail requests
if atomic.LoadInt32(&p.rateLimited) == 1 {
return nil, errors.New("javdb cooling down after 429")
}
<-time.Tick(requestInterval) Type guard
func isRateLimited(err error) bool {
return err != nil && strings.Contains(err.Error(), "429限流")
} Try / catch
magnets, err := p.fetchDetailPageMagnetLinks(url, client)
if isRateLimited(err) {
time.Sleep(cooldownPeriod)
magnets, err = p.fetchDetailPageMagnetLinks(url, client)
} Prevention
- Configure MaxRetryOnRateLimit > 0 so 429s are retried
- Honor the Retry-After header from 429 responses
- Serialize/limit concurrency of detail-page fetches
- Respect the plugin's rateLimited flag and pause the source for a cooldown
- Space requests with a fixed interval when batch-scraping detail pages
When it happens
Trigger: fetchDetailPageMagnetLinks (or another caller) issues requests fast enough that javdb answers 429; either retries are disabled by configuration or attempt >= MaxRetryOnRateLimit is reached while still receiving 429.
Common situations: Scraping many detail pages in a tight loop without delays; shared IP (VPN/datacenter) already throttled; MaxRetryOnRateLimit configured to 0; bursty concurrent searches from multiple users.
Related errors
AI-assisted analysis of fish2018/pansou@beaa561337 (2026-09-07).
Data as JSON: /api/errors/774c874f5bc6fa45.
Report an issue: GitHub.
Appendix: source
Thrown at plugin/javdb/javdb.go:315
continue
}
// 如果不是429,直接返回(无论成功还是其他错误)
if resp.StatusCode != 429 {
return resp, nil
}
// 遇到429
atomic.AddInt32(&p.rateLimitCount, 1)
if p.debugMode {
log.Printf("[JAVDB] 遇到429限流,尝试 %d/%d", attempt+1, MaxRetryOnRateLimit+1)
}
// 如果不允许重试或已达到最大重试次数
if MaxRetryOnRateLimit == 0 || attempt >= MaxRetryOnRateLimit {
atomic.StoreInt32(&p.rateLimited, 1)
resp.Body.Close()
return nil, fmt.Errorf("[%s] 429限流,%s", p.Name(),
func() string {
if MaxRetryOnRateLimit == 0 {
return "不重试"
}
return fmt.Sprintf("重试%d次后仍然限流", MaxRetryOnRateLimit)
}())
}
resp.Body.Close()
lastErr = fmt.Errorf("429 Too Many Requests")
}
return nil, lastErr
}
// parseSearchResults 解析搜索结果HTML
func (p *JavdbPlugin) parseSearchResults(doc *goquery.Document) ([]model.SearchResult, error) {
var results []model.SearchResultView on GitHub (pinned to beaa561337)