fish2018/pansou · error
[ ] 搜索请求失败
Error message
[%s] 搜索请求失败: %w
What it means
The encrypted POST to {apiBaseURL}/{URLVersion}/search failed at the transport/request level: requestJSON returned an error (network failure, timeout, non-decodable body, etc.). The plugin wraps the underlying error so callers see it was the search request that failed, distinct from a non-200 search response.
Solutions
- Inspect the wrapped error for the root cause (DNS, timeout, TLS, status, decode)
- Verify config.URLVersion is current and the versioned /search endpoint exists
- Increase the HTTP client timeout or add retries with backoff for transient failures
- Check network/proxy connectivity to p.apiBaseURL
Example fix
// before
client := &http.Client{} // no timeout, hangs
// after
client := &http.Client{Timeout: 15 * time.Second} // fail fast, then retry transient errors Defensive patterns
Strategy: retry
Validate before calling
u, err := url.Parse(fmt.Sprintf("%s/%s/search", apiBaseURL, url.PathEscape(config.URLVersion)))
if err != nil || u.Host == "" {
return fmt.Errorf("invalid search endpoint URL")
} Try / catch
items, err := p.search(ctx, client, cfg, kw)
if err != nil {
var nerr net.Error
if errors.As(err, &nerr) && (nerr.Timeout() || isTransient(nerr)) {
return retry.WithBackoff(ctx, 3, p.search, ctx, client, cfg, kw)
}
return err
} Prevention
- Set a sane http.Client timeout and retry transient network errors with backoff
- Validate URLVersion before building the endpoint path (PathEscape alone is not enough)
- Monitor search endpoint availability and latency
- Surface the wrapped root cause to logs instead of swallowing it
When it happens
Trigger: p.requestJSON(ctx, client, http.MethodPost, endpoint, encrypted, &response) returns non-nil error in search, where endpoint = p.apiBaseURL+"/"+url.PathEscape(config.URLVersion)+"/search".
Common situations: Network outage, DNS failure, or proxy blocking the search host; request timeout configured too low; an invalid URLVersion produces a 404 or malformed URL; TLS certificate problems; server 5xx with a non-JSON body that requestJSON cannot decode.
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/b660c2a1f76f5902.
Report an issue: GitHub.
Appendix: source
Thrown at plugin/yingso/yingso.go:227
func (p *YingsoPlugin) search(ctx context.Context, client *http.Client, config apiConfig, keyword string) ([]searchItem, error) {
payload := searchPayload{
PageSize: pageSize,
PageNum: 1,
Title: keyword,
Root: 0,
Category: "all",
UserID: config.UserID,
}
encrypted, err := encryptPayload(payload, config)
if err != nil {
return nil, fmt.Errorf("[%s] 生成搜索参数失败: %w", p.Name(), err)
}
var response apiEnvelope[[]searchItem]
endpoint := fmt.Sprintf("%s/%s/search", p.apiBaseURL, url.PathEscape(config.URLVersion))
if err := p.requestJSON(ctx, client, http.MethodPost, endpoint, encrypted, &response); err != nil {
return nil, fmt.Errorf("[%s] 搜索请求失败: %w", p.Name(), err)
}
if response.Code != http.StatusOK {
return nil, fmt.Errorf("[%s] 搜索接口异常: code=%d msg=%s", p.Name(), response.Code, response.Msg)
}
return response.Data, nil
}
func (p *YingsoPlugin) resolveItem(ctx context.Context, client *http.Client, config apiConfig, item searchItem) (model.SearchResult, error) {
payload := getKeyPayload{ID: item.ID, UserID: config.UserID}
encrypted, err := encryptPayload(payload, config)
if err != nil {
return model.SearchResult{}, err
}
var response apiEnvelope[string]
endpoint := fmt.Sprintf("%s/%s/getKey", p.apiBaseURL, url.PathEscape(config.URLVersion))
if err := p.requestJSON(ctx, client, http.MethodPost, endpoint, encrypted, &response); err != nil {
return model.SearchResult{}, errView on GitHub (pinned to beaa561337)