fish2018/pansou · error

web search request failed

Error message

web search request failed: %w

What it means

After building the web search request, searchWeb executes it with client.Do. Any transport-level failure — DNS, connect, TLS, timeout, context deadline — is returned wrapped as 'web search request failed'. The 30-second context timeout surfaces here as well.

Solutions

  1. Check errors.Is(err, context.DeadlineExceeded) to distinguish timeout from connect failure.
  2. Verify outbound network access and DNS resolution for www.panso.vip from the host.
  3. Increase the 30s timeout if the site is consistently slow, or add retry with backoff.
  4. Confirm the site is still reachable/upstream has not blocked your IP (test with curl).

Example fix

// before
resp, err := client.Do(req)
if err != nil {
    return nil, fmt.Errorf("web search request failed: %w", err)
}
// after
resp, err := client.Do(req)
if err != nil {
    if errors.Is(err, context.DeadlineExceeded) {
        return nil, fmt.Errorf("web search request timed out after 30s: %w", err)
    }
    return nil, fmt.Errorf("web search request failed: %w", err)
}
Defensive patterns

Strategy: retry

Try / catch

results, err := plugin.Search(keyword)
if err != nil && strings.Contains(err.Error(), "web search request failed") {
    if errors.Is(errors.Unwrap(err), context.DeadlineExceeded) {
        // timeout: retry with a longer deadline or skip source
    } else {
        // connectivity problem: check DNS/proxy/egress
    }
}

Prevention

When it happens

Trigger: client.Do(req) returns a non-nil error in searchWeb: network unreachable, TLS handshake failure, DNS failure, or the 30s context.WithTimeout expired mid-request.

Common situations: panso.vip blocked or slow from the host, no internet egress, corporate TLS proxy, site temporarily down, or heavy keyword causing a slow response past the 30s deadline.

Related errors


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

Appendix: source

Thrown at plugin/sousou/sousou.go:183

	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) {
		anchor := item.Find("a.search-item-title[href]").First()
		href := strings.TrimSpace(anchor.AttrOr("href", ""))
		if href == "" {
			return
		}

View on GitHub (pinned to beaa561337)