{"record":{"id":"2e2a4dbf178235fc","repo":"fish2018/pansou","slug":"create-request-failed-page-d-type-s-w","errorCode":null,"errorMessage":"create request failed (page %d, type %s): %w","messagePattern":"create request failed \\(page (.+?), type (.+?)\\): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugin/sousou/sousou.go","lineNumber":401,"sourceCode":"\t\t\tapiURL := fmt.Sprintf(\"%s?action=search&q=%s&page=%d&per_size=%d&type=%s\",\n\t\t\t\tSousouAPI,\n\t\t\t\turl.QueryEscape(keyword),\n\t\t\t\tpageNum,\n\t\t\t\tDefaultPerSize,\n\t\t\t\tdiskType,\n\t\t\t)\n\n\t\t\tdebugLog(\"请求URL (page %d, type %s): %s\", pageNum, diskType, apiURL)\n\n\t\t\t// 创建带超时的上下文\n\t\t\tctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)\n\t\t\tdefer cancel()\n\n\t\t\t// 创建请求\n\t\t\treq, err := http.NewRequestWithContext(ctx, \"GET\", apiURL, nil)\n\t\t\tif err != nil {\n\t\t\t\tdebugLog(\"创建请求失败 (page %d, type %s): %v\", pageNum, diskType, err)\n\t\t\t\terrChan <- fmt.Errorf(\"create request failed (page %d, type %s): %w\", pageNum, diskType, err)\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\t// 设置请求头\n\t\t\treq.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\")\n\t\t\treq.Header.Set(\"Accept\", \"application/json, text/plain, */*\")\n\t\t\treq.Header.Set(\"Accept-Language\", \"zh-CN,zh;q=0.9,en;q=0.8\")\n\t\t\treq.Header.Set(\"Connection\", \"keep-alive\")\n\t\t\treq.Header.Set(\"Referer\", \"https://sousou.pro/\")\n\n\t\t\t// 发送请求\n\t\t\tresp, err := client.Do(req)\n\t\t\tif err != nil {\n\t\t\t\tdebugLog(\"请求失败 (page %d, type %s): %v\", pageNum, diskType, err)\n\t\t\t\terrChan <- fmt.Errorf(\"request failed (page %d, type %s): %w\", pageNum, diskType, err)\n\t\t\t\treturn\n\t\t\t}\n\t\t\tdefer resp.Body.Close()","sourceCodeStart":383,"sourceCodeEnd":419,"githubUrl":"https://github.com/fish2018/pansou/blob/beaa56133755a548ebc51b090b3816e2ae044aa6/plugin/sousou/sousou.go#L383-L419","documentation":"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).","triggerScenarios":"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.","commonSituations":"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.","solutions":["URL-encode all interpolated values with url.QueryEscape / url.Values when building apiURL","Log the full apiURL to spot the malformed component and fix the URL construction code","Validate apiURL with url.Parse before the goroutine to fail fast with a clearer message"],"exampleFix":"// before\napiURL := fmt.Sprintf(\"%s/api/search?kw=%s&page=%d&type=%s\", BaseURL, keyword, pageNum, diskType)\n// after\napiURL := fmt.Sprintf(\"%s/api/search?%s\", BaseURL, url.Values{\n    \"kw\": {keyword}, \"page\": {strconv.Itoa(pageNum)}, \"type\": {diskType},\n}.Encode())","handlingStrategy":"validation","validationCode":"u, err := url.Parse(apiURL)\nif err != nil || u.Scheme == \"\" || u.Host == \"\" {\n    return fmt.Errorf(\"invalid apiURL %q: %v\", apiURL, err)\n}","typeGuard":null,"tryCatchPattern":"results, err := searchSousou(...)\nif err != nil && strings.Contains(err.Error(), \"create request failed\") {\n    return fmt.Errorf(\"bad request URL: %w\", err)\n}","preventionTips":["Always build query strings with url.Values.Encode()","Never interpolate raw keywords into URLs","Validate base URLs at startup with url.Parse"],"tags":["http","url","encoding"],"backgroundTag":"invalid-url-format","analyzedSha":"beaa56133755a548ebc51b090b3816e2ae044aa6","analyzedAt":"2026-09-07T00:31:18.025Z","contentChangedAt":"2026-09-07T00:31:18.025Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}