fish2018/pansou · error

create web search request failed

Error message

create web search request failed: %w

What it means

searchWeb builds the panso.vip web search URL (SousouWebURL + encoded keyword) and creates the request with http.NewRequestWithContext. If request construction fails (malformed URL, bad method, invalid query escaping), this wrapped error is returned before any network I/O happens.

Solutions

  1. Print/inspect SousouWebURL; ensure it is a valid absolute http(s) URL.
  2. Validate the URL with url.Parse at plugin init and fail fast with a clear config error.
  3. Ensure the keyword is passed through url.QueryEscape (it already is) and contains no raw newlines.
  4. Fix the base URL in the plugin config/source list if the site moved.

Example fix

// before
searchURL := SousouWebURL + "?q=" + url.QueryEscape(strings.TrimSpace(keyword))
req, err := http.NewRequestWithContext(ctx, http.MethodGet, searchURL, nil)
if err != nil {
    return nil, fmt.Errorf("create web search request failed: %w", err)
}
// after
base, err := url.Parse(SousouWebURL)
if err != nil || base.Scheme == "" || base.Host == "" {
    return nil, fmt.Errorf("invalid SousouWebURL %q: %w", SousouWebURL, err)
}
searchURL := SousouWebURL + "?q=" + url.QueryEscape(strings.TrimSpace(keyword))
Defensive patterns

Strategy: validation

Validate before calling

u, err := url.Parse(SousouWebURL)
if err != nil || u.Scheme == "" || u.Host == "" {
    return fmt.Errorf("invalid SousouWebURL: %q", SousouWebURL)
}

Try / catch

results, err := plugin.Search(keyword)
if err != nil && strings.Contains(err.Error(), "create web search request failed") {
    // config problem: fix SousouWebURL, do not retry
}

Prevention

When it happens

Trigger: http.NewRequestWithContext(ctx, http.MethodGet, SousouWebURL+"?q="+url.QueryEscape(...), nil) returns err inside searchWeb — almost always an invalid SousouWebURL configuration value.

Common situations: SousouWebURL configured with a typo, missing scheme (e.g. 'panso.vip' without https://), control characters in the URL, or an empty config value.

Understand the failure class

Background: "Invalid URL" errors: why new URL(), URI.parse, and reqwest::Url reject your string — missing scheme, whitespace, and bad path format — this error's family across 39 libraries.

Related errors


AI-assisted analysis of fish2018/pansou@beaa561337 (2026-09-07). Data as JSON: /api/errors/0b8b3d253a35e8d7. Report an issue: GitHub.

Appendix: source

Thrown at plugin/sousou/sousou.go:178

}

type pansoSearchItem struct {
	DocURL   string
	Title    string
	Content  string
	DiskType string
	Datetime time.Time
	Password string
}

func (p *SousouAsyncPlugin) searchWeb(client *http.Client, keyword string) ([]model.SearchResult, error) {
	ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
	defer cancel()

	searchURL := SousouWebURL + "?q=" + url.QueryEscape(strings.TrimSpace(keyword))
	req, err := http.NewRequestWithContext(ctx, http.MethodGet, searchURL, nil)
	if err != nil {
		return nil, fmt.Errorf("create web search request failed: %w", err)
	}
	setSousouWebHeaders(req, "https://www.panso.vip/")
	resp, err := client.Do(req)
	if err != nil {
		return nil, fmt.Errorf("web search request failed: %w", err)
	}
	defer resp.Body.Close()
	if resp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("web search returned status %d", resp.StatusCode)
	}

	doc, err := goquery.NewDocumentFromReader(resp.Body)
	if err != nil {
		return nil, fmt.Errorf("parse web search page failed: %w", err)
	}

	items := make([]pansoSearchItem, 0, 20)
	doc.Find("div.search-item").Each(func(_ int, item *goquery.Selection) {

View on GitHub (pinned to beaa561337)