fish2018/pansou · error

create request failed

Error message

create request failed (page %d, type %s): %w

What it means

Inside the concurrent page-fetch worker for the sousou API, http.NewRequestWithContext failed to construct the GET request; the raw error is wrapped with page number and disk type and sent to errChan. This almost always means the URL failed parsing (http.NewRequest returns an error only for malformed URLs or a bad context).

Solutions

  1. URL-encode all interpolated values with url.QueryEscape / url.Values when building apiURL
  2. Log the full apiURL to spot the malformed component and fix the URL construction code
  3. Validate apiURL with url.Parse before the goroutine to fail fast with a clearer message

Example fix

// before
apiURL := fmt.Sprintf("%s/api/search?kw=%s&page=%d&type=%s", BaseURL, keyword, pageNum, diskType)
// after
apiURL := fmt.Sprintf("%s/api/search?%s", BaseURL, url.Values{
    "kw": {keyword}, "page": {strconv.Itoa(pageNum)}, "type": {diskType},
}.Encode())
Defensive patterns

Strategy: validation

Validate before calling

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

Try / catch

results, err := searchSousou(...)
if err != nil && strings.Contains(err.Error(), "create request failed") {
    return fmt.Errorf("bad request URL: %w", err)
}

Prevention

When it happens

Trigger: apiURL built for (pageNum, diskType) is malformed — e.g. improperly escaped query parameters, control characters, or an invalid base URL — causing http.NewRequestWithContext to return an error.

Common situations: Search keyword contains characters not URL-escaped (spaces, &, #) when interpolated into apiURL; a misconfigured base URL constant; diskType value injected into the URL without encoding.

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

Appendix: source

Thrown at plugin/sousou/sousou.go:401

			apiURL := fmt.Sprintf("%s?action=search&q=%s&page=%d&per_size=%d&type=%s",
				SousouAPI,
				url.QueryEscape(keyword),
				pageNum,
				DefaultPerSize,
				diskType,
			)

			debugLog("请求URL (page %d, type %s): %s", pageNum, diskType, apiURL)

			// 创建带超时的上下文
			ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
			defer cancel()

			// 创建请求
			req, err := http.NewRequestWithContext(ctx, "GET", apiURL, nil)
			if err != nil {
				debugLog("创建请求失败 (page %d, type %s): %v", pageNum, diskType, err)
				errChan <- fmt.Errorf("create request failed (page %d, type %s): %w", pageNum, diskType, err)
				return
			}

			// 设置请求头
			req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36")
			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("Connection", "keep-alive")
			req.Header.Set("Referer", "https://sousou.pro/")

			// 发送请求
			resp, err := client.Do(req)
			if err != nil {
				debugLog("请求失败 (page %d, type %s): %v", pageNum, diskType, err)
				errChan <- fmt.Errorf("request failed (page %d, type %s): %w", pageNum, diskType, err)
				return
			}
			defer resp.Body.Close()

View on GitHub (pinned to beaa561337)