fish2018/pansou · error
[ ] 创建搜索请求失败
Error message
[%s] 创建搜索请求失败: %w
What it means
This error is returned by MiosouPlugin.searchImpl when http.NewRequestWithContext fails to construct the GET request to apiBaseURL + "/search?keyword=...". With a constant apiBaseURL this almost always means the URL failed to parse (url.Parse error inside NewRequest) or the context is invalid — a programming/config-level problem rather than a network issue.
Solutions
- Print the constructed URL and validate it (http.NewRequest manually or url.Parse) to find the malformed part
- Check apiBaseURL configuration for stray whitespace, missing scheme, or illegal characters
- Ensure the context passed to WithTimeout is fresh, not already canceled
- Since this is deterministic, fix the config/code; retrying will not help
Example fix
// before (misconfigured base)
apiBaseURL = "miosou.example.com/api" // missing scheme
// after
apiBaseURL = "https://miosou.example.com/api"
u, err := url.Parse(apiBaseURL)
if err != nil || u.Scheme == "" {
log.Fatalf("invalid apiBaseURL: %v", err)
} Defensive patterns
Strategy: validation
Validate before calling
// Go: validate the API URL at startup
u, err := url.Parse(apiBaseURL)
if err != nil || u.Scheme == "" || u.Host == "" {
return fmt.Errorf("invalid apiBaseURL %q: %v", apiBaseURL, err)
} Type guard
func validHTTPURL(raw string) bool {
u, err := url.Parse(raw)
return err == nil && (u.Scheme == "http" || u.Scheme == "https") && u.Host != ""
} Try / catch
if req, err = http.NewRequestWithContext(ctx, http.MethodGet, reqURL, nil); err != nil {
return nil, fmt.Errorf("constructing search request for %q: %w", reqURL, err)
} Prevention
- Validate baseURL configuration at plugin init, not per-request
- Keep URL construction with url.Values and url.QueryEscape
- Never build URLs by naive string concatenation of untrusted input
- Unit-test request construction with the real constant
When it happens
Trigger: searchImpl builds the request on each of its 2 attempts; NewRequestWithContext returns err when the method or URL is invalid — e.g. apiBaseURL was misconfigured to contain spaces or control characters, or the URL is malformed so url.Parse fails.
Common situations: A build-time misconfiguration of apiBaseURL (bad constant, env override with whitespace or an invalid scheme); a keyword so unusual it breaks URL construction (rare, since url.QueryEscape is applied); passing a nil/already-canceled context from refactored code.
Understand the failure class
Background: "Invalid URL" / "URL cannot be empty": fix the malformed or missing URL behind request-construction failures — this error's family across 50 libraries.
Related errors
AI-assisted analysis of fish2018/pansou@beaa561337 (2026-09-07).
Data as JSON: /api/errors/b681dd1690c9110b.
Report an issue: GitHub.
Appendix: source
Thrown at plugin/miosou/miosou.go:98
func (p *MiosouPlugin) SearchWithResult(keyword string, ext map[string]interface{}) (model.PluginSearchResult, error) {
return p.AsyncSearchWithResult(keyword, p.searchImpl, p.MainCacheKey, ext)
}
func (p *MiosouPlugin) searchImpl(_ *http.Client, keyword string, _ map[string]interface{}) ([]model.SearchResult, error) {
keyword = strings.TrimSpace(keyword)
if keyword == "" {
return nil, nil
}
if err := p.ensureGate(); err != nil {
return nil, err
}
for attempt := 0; attempt < 2; attempt++ {
ctx, cancel := context.WithTimeout(context.Background(), requestTimeout)
req, err := http.NewRequestWithContext(ctx, http.MethodGet, apiBaseURL+"/search?keyword="+url.QueryEscape(keyword), nil)
if err != nil {
cancel()
return nil, fmt.Errorf("[%s] 创建搜索请求失败: %w", p.Name(), err)
}
setHeaders(req, "text/event-stream")
resp, err := p.client.Do(req)
if err != nil {
cancel()
return nil, fmt.Errorf("[%s] 搜索请求失败: %w", p.Name(), err)
}
if isAnubisGateResponse(resp) {
resp.Body.Close()
cancel()
p.invalidateGate()
if err := p.ensureGate(); err != nil {
return nil, err
}
continue
}
if resp.StatusCode != http.StatusOK {
resp.Body.Close()View on GitHub (pinned to beaa561337)