fish2018/pansou · error
cloudscraper not initialized
Error message
cloudscraper not initialized
What it means
PanzunPlugin.searchImpl returns this error when the plugin's cloudscraper client (p.scraper) is still nil when a search is executed. The scraper must be created during plugin construction (NewPanzunPlugin) before AsyncSearchWithResult dispatches searchImpl in a worker. A nil scraper means every HTTP request would panic, so the code fails fast with this sentinel error.
Solutions
- Instantiate the plugin only through its constructor so p.scraper is set before search
- Add a lazy-init or nil check that creates the scraper on first use if it is nil
- Verify the scraper construction code isn't gated behind a config/env condition that is false in this environment
Example fix
// before
p := &panzun.PanzunPlugin{}
results, err := p.Search(keyword, nil) // error: cloudscraper not initialized
// after
p := panzun.NewPanzunPlugin()
results, err := p.Search(keyword, nil) Defensive patterns
Strategy: validation
Validate before calling
if p == nil || p.scraper == nil {
return fmt.Errorf("plugin not initialized: scraper is nil")
}
_ = p.Search(keyword, ext) Type guard
func (p *PanzunPlugin) ready() bool { return p != nil && p.scraper != nil } Try / catch
results, err := plugin.Search(keyword, ext)
if err != nil {
if strings.Contains(err.Error(), "cloudscraper not initialized") {
plugin = panzun.NewPanzunPlugin() // rebuild and retry once
results, err = plugin.Search(keyword, ext)
}
} Prevention
- Always construct plugins via their constructor, never struct literals
- Add an assert-ready check in plugin registration
- Cover constructor initialization with a unit test
When it happens
Trigger: Calling Search/SearchWithResult on a PanzunPlugin instance constructed without initializing p.scraper — e.g. a zero-value PanzunPlugin{} created by hand instead of via the plugin's constructor, or scraper initialization skipped/failing silently before registration.
Common situations: Plugin registered but its constructor bypassed (manual instantiation, reflection-based loading, config-driven creation that doesn't call init code); refactor moved scraper creation out of the constructor; tests instantiating the struct directly.
Related errors
AI-assisted analysis of fish2018/pansou@beaa561337 (2026-09-07).
Data as JSON: /api/errors/a6535d909f1300bc.
Report an issue: GitHub.
Appendix: source
Thrown at plugin/panzun/panzun.go:110
},
}
}
func (p *PanzunPlugin) Search(keyword string, ext map[string]interface{}) ([]model.SearchResult, error) {
result, err := p.SearchWithResult(keyword, ext)
if err != nil {
return nil, err
}
return result.Results, nil
}
func (p *PanzunPlugin) SearchWithResult(keyword string, ext map[string]interface{}) (model.PluginSearchResult, error) {
return p.AsyncSearchWithResult(keyword, p.searchImpl, p.MainCacheKey, ext)
}
func (p *PanzunPlugin) searchImpl(client *http.Client, keyword string, ext map[string]interface{}) ([]model.SearchResult, error) {
if p.scraper == nil {
return nil, fmt.Errorf("cloudscraper not initialized")
}
var allResults []model.SearchResult
seenIDs := make(map[string]bool)
for page := 1; page <= maxPages; page++ {
offset := (page - 1) * pageSize
searchURL := fmt.Sprintf("%s/discussions?filter[q]=%s&page[offset]=%d", apiBase, url.QueryEscape(keyword), offset)
resp, err := p.scraper.Get(searchURL)
if err != nil {
if len(allResults) > 0 {
fmt.Printf("[%s] Warning: failed to fetch page %d: %v\n", p.Name(), page, err)
break
}
return nil, fmt.Errorf("[%s] search request failed on page %d: %w", p.Name(), page, err)
}
View on GitHub (pinned to beaa561337)