fish2018/pansou · error

[ ] 搜索会话请求失败

Error message

[%s] 搜索会话请求失败: %w

What it means

ensureSearchSession wraps errors from client.Do when the session-establishment request to /api/search/session fails at transport level. Without a successful session the subsequent search may fail, so this is a prerequisite-step failure. The cause is preserved via %w.

Solutions

  1. Unwrap the error to identify timeout vs connection failure.
  2. curl jupansouBaseURL/api/search/session from the host to confirm reachability.
  3. Increase jupansouTimeout if the endpoint is slow.
  4. Update the plugin if the upstream removed or moved the session endpoint.
  5. Check proxy/firewall rules for the deployment host.
Defensive patterns

Strategy: try-catch

Validate before calling

conn, err := net.DialTimeout("tcp", host, 3*time.Second)
if err != nil { return fmt.Errorf("upstream unreachable before search: %w", err) }
conn.Close()

Try / catch

if err := p.ensureSearchSession(client); err != nil {
    var nerr net.Error
    if errors.As(err, &nerr) && nerr.Timeout() {
        log.Println("session establishment timed out; retrying with longer timeout")
    } else {
        log.Printf("session request failed: %v", err)
    }
    // degrade: proceed without session or skip this source
}

Prevention

When it happens

Trigger: client.Do for the session request returns an error: DNS failure, connection refused, TLS error, or the jupansouTimeout context expiring before a response arrives.

Common situations: Upstream site down or domain changed; the session endpoint removed/blocked; network egress blocked in the deployment environment; jupansouTimeout too short for a slow upstream.

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/9163fb64aca2f5ba. Report an issue: GitHub.

Appendix: source

Thrown at plugin/jupansou/jupansou.go:183

	results := p.exchangeItems(client, filteredItems)
	return plugin.FilterResultsByKeyword(results, keyword), nil
}

func (p *JuPansouPlugin) ensureSearchSession(client *http.Client) error {
	ctx, cancel := context.WithTimeout(context.Background(), jupansouTimeout)
	defer cancel()
	req, err := http.NewRequestWithContext(ctx, http.MethodGet, jupansouBaseURL+"/api/search/session", nil)
	if err != nil {
		return fmt.Errorf("[%s] 创建搜索会话请求失败: %w", p.Name(), err)
	}
	req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/124.0 Safari/537.36")
	req.Header.Set("Accept", "application/json")
	req.Header.Set("Referer", jupansouBaseURL+"/")
	req.Header.Set("X-Requested-With", "XMLHttpRequest")
	resp, err := client.Do(req)
	if err != nil {
		return fmt.Errorf("[%s] 搜索会话请求失败: %w", p.Name(), err)
	}
	defer resp.Body.Close()
	if resp.StatusCode != http.StatusOK {
		return fmt.Errorf("[%s] 搜索会话返回状态码: %d", p.Name(), resp.StatusCode)
	}
	return nil
}

func (p *JuPansouPlugin) exchangeItems(client *http.Client, items []juPansouStreamItem) []model.SearchResult {
	results := make([]model.SearchResult, 0, len(items))
	var wg sync.WaitGroup
	var mu sync.Mutex
	sem := make(chan struct{}, 8)
	seen := make(map[string]struct{})
	for _, item := range items {
		item := item
		if item.URL == "" {
			continue

View on GitHub (pinned to beaa561337)