{"record":{"id":"08c6361f126b63e8","repo":"Tencent/WeKnora","slug":"invalid-proxy-url-scheme-and-host-are-required","errorCode":null,"errorMessage":"invalid proxy_url: scheme and host are required","messagePattern":"invalid proxy_url: scheme and host are required","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/infrastructure/web_search/proxy.go","lineNumber":43,"sourceCode":"func NewSearchHTTPClient(timeout time.Duration, proxyURL string) (*http.Client, error) {\n\tproxyURL = strings.TrimSpace(proxyURL)\n\tdef, ok := http.DefaultTransport.(*http.Transport)\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"default HTTP transport is not *http.Transport\")\n\t}\n\tt := def.Clone()\n\tt.DialContext = utils.SSRFSafeDialContext\n\n\tif proxyURL != \"\" {\n\t\tif err := ValidateProxyURL(proxyURL); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tu, err := url.Parse(proxyURL)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"invalid proxy_url: %w\", err)\n\t\t}\n\t\tif u.Scheme == \"\" || u.Host == \"\" {\n\t\t\treturn nil, fmt.Errorf(\"invalid proxy_url: scheme and host are required\")\n\t\t}\n\t\tt.Proxy = http.ProxyURL(u)\n\t} else {\n\t\tt.Proxy = http.ProxyFromEnvironment\n\t}\n\n\tcfg := utils.DefaultSSRFSafeHTTPClientConfig()\n\tcfg.Timeout = timeout\n\treturn utils.NewSSRFSafeHTTPClientWithTransport(cfg, t), nil\n}\n","sourceCodeStart":25,"sourceCodeEnd":54,"githubUrl":"https://github.com/Tencent/WeKnora/blob/988cbb03305e055d8ebb7d46d9ac6cc0803cd074/internal/infrastructure/web_search/proxy.go#L25-L54","documentation":"The proxy_url parsed successfully but lacks a scheme or a host, so it cannot be used as an HTTP proxy URL. This is a validation error distinct from parse failures; the URL syntax was fine but semantically incomplete.","triggerScenarios":"NewSearchHTTPClient called with values like \"localhost:8080\" (no scheme; url.Parse treats it as path-only), \"/path/to/sock\", or \"\" is allowed but \"http://\" (empty host) triggers this.","commonSituations":"Config values like \"proxy.company.com:3128\" without http://, YAML interpolation dropping the scheme, users entering only a hostname from proxy docs.","solutions":["Add the scheme: change \"localhost:8080\" to \"http://localhost:8080\"","Ensure the host is present, not just a scheme","Run ValidateProxyURL/url.Parse checks on config at startup, before provider creation","For SOCKS, use socks5:// explicitly"],"exampleFix":"// before\nproxyURL := \"10.0.0.5:3128\"\n// after\nproxyURL := \"http://10.0.0.5:3128\"","handlingStrategy":"validation","validationCode":"func hasSchemeAndHost(raw string) bool {\n    u, err := url.Parse(strings.TrimSpace(raw))\n    return err == nil && u.Scheme != \"\" && u.Host != \"\"\n}\n// usage: if proxyURL != \"\" && !hasSchemeAndHost(proxyURL) { ... reject ... }","typeGuard":null,"tryCatchPattern":"client, err := web_search.NewSearchHTTPClient(timeout, proxyURL)\nif err != nil {\n    if strings.Contains(err.Error(), \"scheme and host are required\") {\n        return fmt.Errorf(\"proxy_url %q needs scheme and host, e.g. http://proxy:8080\", proxyURL)\n    }\n    return err\n}","preventionTips":["Always include the scheme (http://, https://, socks5://) in proxy config","Add a UI/config-level regex check like ^[a-z][a-z0-9+.-]*://","Normalize config values with strings.TrimSpace before use","Document the expected format next to the proxy_url field"],"tags":["url","proxy","configuration","validation"],"backgroundTag":"invalid-proxy-url","analyzedSha":"988cbb03305e055d8ebb7d46d9ac6cc0803cd074","analyzedAt":"2026-09-02T14:41:08.344Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}