{"record":{"id":"0b8b3d253a35e8d7","repo":"fish2018/pansou","slug":"create-web-search-request-failed-w","errorCode":null,"errorMessage":"create web search request failed: %w","messagePattern":"create web search request failed: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugin/sousou/sousou.go","lineNumber":178,"sourceCode":"}\n\ntype pansoSearchItem struct {\n\tDocURL   string\n\tTitle    string\n\tContent  string\n\tDiskType string\n\tDatetime time.Time\n\tPassword string\n}\n\nfunc (p *SousouAsyncPlugin) searchWeb(client *http.Client, keyword string) ([]model.SearchResult, error) {\n\tctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)\n\tdefer cancel()\n\n\tsearchURL := SousouWebURL + \"?q=\" + url.QueryEscape(strings.TrimSpace(keyword))\n\treq, err := http.NewRequestWithContext(ctx, http.MethodGet, searchURL, nil)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"create web search request failed: %w\", err)\n\t}\n\tsetSousouWebHeaders(req, \"https://www.panso.vip/\")\n\tresp, err := client.Do(req)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"web search request failed: %w\", err)\n\t}\n\tdefer resp.Body.Close()\n\tif resp.StatusCode != http.StatusOK {\n\t\treturn nil, fmt.Errorf(\"web search returned status %d\", resp.StatusCode)\n\t}\n\n\tdoc, err := goquery.NewDocumentFromReader(resp.Body)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"parse web search page failed: %w\", err)\n\t}\n\n\titems := make([]pansoSearchItem, 0, 20)\n\tdoc.Find(\"div.search-item\").Each(func(_ int, item *goquery.Selection) {","sourceCodeStart":160,"sourceCodeEnd":196,"githubUrl":"https://github.com/fish2018/pansou/blob/beaa56133755a548ebc51b090b3816e2ae044aa6/plugin/sousou/sousou.go#L160-L196","documentation":"searchWeb builds the panso.vip web search URL (SousouWebURL + encoded keyword) and creates the request with http.NewRequestWithContext. If request construction fails (malformed URL, bad method, invalid query escaping), this wrapped error is returned before any network I/O happens.","triggerScenarios":"http.NewRequestWithContext(ctx, http.MethodGet, SousouWebURL+\"?q=\"+url.QueryEscape(...), nil) returns err inside searchWeb — almost always an invalid SousouWebURL configuration value.","commonSituations":"SousouWebURL configured with a typo, missing scheme (e.g. 'panso.vip' without https://), control characters in the URL, or an empty config value.","solutions":["Print/inspect SousouWebURL; ensure it is a valid absolute http(s) URL.","Validate the URL with url.Parse at plugin init and fail fast with a clear config error.","Ensure the keyword is passed through url.QueryEscape (it already is) and contains no raw newlines.","Fix the base URL in the plugin config/source list if the site moved."],"exampleFix":"// before\nsearchURL := SousouWebURL + \"?q=\" + url.QueryEscape(strings.TrimSpace(keyword))\nreq, err := http.NewRequestWithContext(ctx, http.MethodGet, searchURL, nil)\nif err != nil {\n    return nil, fmt.Errorf(\"create web search request failed: %w\", err)\n}\n// after\nbase, err := url.Parse(SousouWebURL)\nif err != nil || base.Scheme == \"\" || base.Host == \"\" {\n    return nil, fmt.Errorf(\"invalid SousouWebURL %q: %w\", SousouWebURL, err)\n}\nsearchURL := SousouWebURL + \"?q=\" + url.QueryEscape(strings.TrimSpace(keyword))","handlingStrategy":"validation","validationCode":"u, err := url.Parse(SousouWebURL)\nif err != nil || u.Scheme == \"\" || u.Host == \"\" {\n    return fmt.Errorf(\"invalid SousouWebURL: %q\", SousouWebURL)\n}","typeGuard":null,"tryCatchPattern":"results, err := plugin.Search(keyword)\nif err != nil && strings.Contains(err.Error(), \"create web search request failed\") {\n    // config problem: fix SousouWebURL, do not retry\n}","preventionTips":["Validate configured base URLs at plugin startup with url.Parse","Always require an absolute http(s) URL in config","Never build URLs by raw concatenation with unescaped user input","Add a startup smoke-test request per source"],"tags":["http","url","configuration","go"],"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"}