{"record":{"id":"e80afbd5c525b130","repo":"fish2018/pansou","slug":"w-e80afb","errorCode":null,"errorMessage":"解析搜索地址失败: %w","messagePattern":"解析搜索地址失败: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugin/xiaokupan/xiaokupan.go","lineNumber":118,"sourceCode":"\t\t}\n\t\tresults, err = p.searchWithFunctionID(client, keyword, refreshedID)\n\t}\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"[%s] 搜索失败: %w\", p.Name(), err)\n\t}\n\treturn plugin.FilterResultsByKeyword(results, keyword), nil\n}\n\nfunc (p *XiaokupanPlugin) searchWithFunctionID(client *http.Client, keyword, functionID string) ([]model.SearchResult, error) {\n\tpayload, err := buildSearchPayload(keyword)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"构造搜索参数失败: %w\", err)\n\t}\n\n\tendpoint := fmt.Sprintf(\"%s/_serverFn/%s\", strings.TrimRight(p.baseURL, \"/\"), functionID)\n\tparsedEndpoint, err := url.Parse(endpoint)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"解析搜索地址失败: %w\", err)\n\t}\n\tquery := parsedEndpoint.Query()\n\tquery.Set(\"payload\", string(payload))\n\tparsedEndpoint.RawQuery = query.Encode()\n\n\tctx, cancel := context.WithTimeout(context.Background(), requestTimeout)\n\tdefer cancel()\n\n\treq, err := http.NewRequestWithContext(ctx, http.MethodGet, parsedEndpoint.String(), nil)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"创建搜索请求失败: %w\", err)\n\t}\n\tp.setSearchHeaders(req, keyword)\n\n\tbody, err := doLimitedRequest(client, req, maxSearchResponseSize)\n\tif err != nil {\n\t\treturn nil, err\n\t}","sourceCodeStart":100,"sourceCodeEnd":136,"githubUrl":"https://github.com/fish2018/pansou/blob/beaa56133755a548ebc51b090b3816e2ae044aa6/plugin/xiaokupan/xiaokupan.go#L100-L136","documentation":"Wraps an error from url.Parse when constructing the search endpoint URL \"%s/_serverFn/%s\" from the plugin's baseURL and the server function ID. Indicates the assembled endpoint is not a valid URL — almost always because baseURL is misconfigured rather than a bad functionID (which is a plain hex hash).","triggerScenarios":"url.Parse fails on baseURL+\"/_serverFn/\"+functionID — e.g. baseURL contains characters illegal in a URL (spaces, unescaped control chars, stray percent signs like 'https://xiaokupan.com%'), or a custom baseURL was set to a malformed value.","commonSituations":"Operator misconfigures the plugin's base URL (typo, extra protocol, unescaped characters); environment substitution injects whitespace into the URL; copy-pasted URL with trailing invisible characters.","solutions":["Print/inspect the exact endpoint string that failed to parse","Validate the configured baseURL: it must include scheme (https://) and contain no spaces or stray '%' escapes","Run url.Parse on the baseURL alone to isolate which part is invalid","Percent-encode or strip invalid characters before composing the endpoint"],"exampleFix":"// before\nendpoint := fmt.Sprintf(\"%s/_serverFn/%s\", strings.TrimRight(p.baseURL, \"/\"), functionID)\nparsedEndpoint, err := url.Parse(endpoint)\n// after: validate the base up front\nif _, err := url.Parse(p.baseURL); err != nil {\n    return nil, fmt.Errorf(\"invalid baseURL %q: %w\", p.baseURL, err)\n}\nendpoint := fmt.Sprintf(\"%s/_serverFn/%s\", strings.TrimRight(p.baseURL, \"/\"), functionID)\nparsedEndpoint, err := url.Parse(endpoint)","handlingStrategy":"validation","validationCode":"func validateBaseURL(raw string) error {\n    u, err := url.Parse(raw)\n    if err != nil { return err }\n    if u.Scheme == \"\" || u.Host == \"\" { return fmt.Errorf(\"baseURL %q needs scheme and host\", raw) }\n    return nil\n}\nif err := validateBaseURL(cfg.XiaokupanBaseURL); err != nil { /* reject config */ }","typeGuard":"func isUsableURL(u *url.URL) bool { return u != nil && u.Scheme != \"\" && u.Host != \"\" }","tryCatchPattern":"if err != nil {\n    var urlErr *url.Error\n    if errors.As(err, &urlErr) {\n        log.Printf(\"malformed endpoint %q: %v\", endpoint, urlErr)\n    }\n    return err\n}","preventionTips":["Always configure baseURL as an absolute URL with https:// scheme","Trim and validate config values before injecting them into URL templates","Escape/encode any dynamic segment before string-formatting into a URL"],"tags":["url","config","search"],"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"}