fish2018/pansou · error

request failed

Error message

request failed: %w

What it means

searchPage executes the POST via client.Do; any transport-level failure (connection refused, DNS resolution failure, TLS error, or context deadline exceeded from the DefaultTimeout timeout) is wrapped as "request failed: %w". Unlike status errors, this fires before an HTTP response is obtained.

Solutions

  1. Unwrap the error and check for context.DeadlineExceeded — if so, the timeout was hit; consider increasing DefaultTimeout
  2. Verify network connectivity and DNS resolution of www.melost.cn from the host (curl the endpoint manually)
  3. If behind a proxy/firewall, configure the http.Client's Transport proxy settings
  4. Retry later if the upstream site is down; note only page-level errors are aggregated by doSearch

Example fix

// before
resp, err := client.Do(req)
if err != nil {
	return nil, fmt.Errorf("request failed: %w", err)
}
// after: distinguish timeout vs transport
resp, err := client.Do(req)
if err != nil {
	if errors.Is(err, context.DeadlineExceeded) {
		return nil, fmt.Errorf("request timed out after %v: %w", DefaultTimeout, err)
	}
	return nil, fmt.Errorf("request failed: %w", err)
}
Defensive patterns

Strategy: retry

Validate before calling

// resolve DNS before searching
if _, err := net.LookupHost("www.melost.cn"); err != nil {
	return nil, fmt.Errorf("melost DNS unreachable: %w", err)
}

Try / catch

resp, err := client.Do(req)
if err != nil {
	if errors.Is(err, context.DeadlineExceeded) {
		// retry with longer timeout
	}
	if isTransientNetErr(err) { // connection refused/reset, EOF
		// retry with backoff
	}
	return nil, fmt.Errorf("request failed: %w", err)
}

Prevention

When it happens

Trigger: client.Do(req) returns an error during a page search: network unreachable, DNS failure for www.melost.cn, TLS handshake failure, connection refused/reset, or the per-request context.WithTimeout(DefaultTimeout) expiring mid-request.

Common situations: Deployment host has no internet access or DNS issues, a corporate proxy blocks melost.cn, the site is down or geo-blocked, or slow upstream responses exceed DefaultTimeout.

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/2d5113686b5b4e15. Report an issue: GitHub.

Appendix: source

Thrown at plugin/melost/melost.go:172

	ctx, cancel := context.WithTimeout(context.Background(), DefaultTimeout)
	defer cancel()

	req, err := http.NewRequestWithContext(ctx, "POST", MelostSearchAPI, bytes.NewBuffer(jsonData))
	if err != nil {
		return nil, fmt.Errorf("create request failed: %w", err)
	}

	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("Accept", "application/json, text/plain, */*")
	req.Header.Set("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8")
	req.Header.Set("Origin", "https://www.melost.cn")
	req.Header.Set("Referer", DefaultReferer)
	req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36")

	resp, err := client.Do(req)
	if err != nil {
		return nil, fmt.Errorf("request failed: %w", err)
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("unexpected status code: %d", resp.StatusCode)
	}

	respBody, err := io.ReadAll(resp.Body)
	if err != nil {
		return nil, fmt.Errorf("read response failed: %w", err)
	}

	var apiResp MelostResponse
	if err := json.Unmarshal(respBody, &apiResp); err != nil {
		return nil, fmt.Errorf("decode response failed: %w", err)
	}

	if apiResp.Code != 200 {

View on GitHub (pinned to beaa561337)