{"record":{"id":"4a946c5cfe8a9374","repo":"fish2018/pansou","slug":"get-w-4a946c","errorCode":null,"errorMessage":"创建GET请求失败: %w","messagePattern":"创建GET请求失败: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugin/xdpan/xdpan.go","lineNumber":103,"sourceCode":"\tfilteredResults := plugin.FilterResultsByKeyword(searchResults, keyword)\n\tif DebugLog {\n\t\tfmt.Printf(\"[xdpan] 关键词过滤后: 过滤前=%d, 过滤后=%d\\n\", len(searchResults), len(filteredResults))\n\t}\n\n\treturn filteredResults, nil\n}\n\n// fetchSearchResults 获取搜索结果\nfunc (p *XdpanPlugin) fetchSearchResults(client *http.Client, keyword string) ([]model.SearchResult, error) {\n\t// 构建搜索URL（只获取第一页）\n\tsearchURL := fmt.Sprintf(\"%s/search?page=1&k=%s&p=baidu\", strings.TrimRight(p.baseURL, \"/\"), url.QueryEscape(keyword))\n\n\tctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)\n\tdefer cancel()\n\n\treq, err := http.NewRequestWithContext(ctx, \"GET\", searchURL, nil)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"创建GET请求失败: %w\", err)\n\t}\n\n\tp.setRequestHeaders(req)\n\n\tif DebugLog {\n\t\tfmt.Printf(\"[xdpan] 搜索URL: %s\\n\", searchURL)\n\t}\n\n\tresp, err := p.doRequestWithRetry(req, client)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"GET请求失败: %w\", err)\n\t}\n\tdefer resp.Body.Close()\n\n\tif resp.StatusCode != http.StatusOK {\n\t\treturn nil, fmt.Errorf(\"请求返回状态码: %d\", resp.StatusCode)\n\t}\n","sourceCodeStart":85,"sourceCodeEnd":121,"githubUrl":"https://github.com/fish2018/pansou/blob/beaa56133755a548ebc51b090b3816e2ae044aa6/plugin/xdpan/xdpan.go#L85-L121","documentation":"xdpan's fetchSearchResults builds the search GET request with http.NewRequestWithContext. If request construction fails (invalid method/URL, unparsable target), it wraps the error as this message. With a fixed 'GET' method this almost always means the assembled search URL is invalid.","triggerScenarios":"http.NewRequestWithContext returns an error because the searchURL '%s/search?page=1&k=%s&p=baidu' is malformed — e.g. baseURL is empty, contains whitespace/control characters, or the URL-escaped keyword produced an invalid URL string.","commonSituations":"Missing or misconfigured xdpan baseURL (empty config field); trailing newline in a config value; keyword containing raw control characters; programmatic use passing a non-URL base.","solutions":["Verify the xdpan baseURL configuration is set and is a valid absolute HTTP(S) URL.","Trim whitespace/newlines from the configured base URL before use.","Log the final searchURL to spot malformed composition (double schemes, missing host).","Sanitize/strictly escape the keyword before inserting it into the query string."],"exampleFix":"// before\nsearchURL := fmt.Sprintf(\"%s/search?page=1&k=%s&p=baidu\", strings.TrimRight(p.baseURL, \"/\"), url.QueryEscape(keyword))\n// after: validate the base URL first\nbase := strings.TrimSpace(strings.TrimRight(p.baseURL, \"/\"))\nif u, err := url.Parse(base); err != nil || u.Scheme == \"\" || u.Host == \"\" {\n\treturn nil, fmt.Errorf(\"无效的baseURL配置: %q\", p.baseURL)\n}\nsearchURL := fmt.Sprintf(\"%s/search?page=1&k=%s&p=baidu\", base, url.QueryEscape(keyword))","handlingStrategy":"validation","validationCode":"u, err := url.Parse(cfg.BaseURL)\nif err != nil || u.Scheme == \"\" || u.Host == \"\" {\n\treturn fmt.Errorf(\"invalid baseURL: %q\", cfg.BaseURL)\n}","typeGuard":null,"tryCatchPattern":"results, err := pluginSearch(keyword)\nif err != nil && strings.Contains(err.Error(), \"创建GET请求失败\") {\n\t// invalid URL — check and correct baseURL config before retrying\n}","preventionTips":["Validate baseURL at plugin startup, not per-request.","Trim whitespace/newlines from config values.","Escape keywords with url.QueryEscape before composing URLs."],"tags":["http","url","config","request-construction"],"backgroundTag":"invalid-url","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"}