{"record":{"id":"cb3384231249a596","repo":"Tencent/WeKnora","slug":"failed-to-create-request-w-cb3384","errorCode":null,"errorMessage":"failed to create request: %w","messagePattern":"failed to create request: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/infrastructure/web_search/keenable.go","lineNumber":89,"sourceCode":"\t\tmaxResults = defaultKeenableResults\n\t}\n\n\t// Keyless by default; a configured key switches to the authenticated path.\n\tpath := \"/v1/search/public\"\n\tif p.apiKey != \"\" {\n\t\tpath = \"/v1/search\"\n\t}\n\tendpoint := p.baseURL + path\n\tlogger.Infof(ctx, \"[WebSearch][Keenable] query=%q maxResults=%d url=%s\", query, maxResults, endpoint)\n\n\tbodyBytes, err := json.Marshal(keenableSearchRequest{Query: query, Mode: \"pro\"})\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to marshal request: %w\", err)\n\t}\n\n\treq, err := http.NewRequestWithContext(ctx, \"POST\", endpoint, bytes.NewReader(bodyBytes))\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to create request: %w\", err)\n\t}\n\treq.Header.Set(\"Content-Type\", \"application/json\")\n\treq.Header.Set(\"Accept\", \"application/json\")\n\treq.Header.Set(\"X-Keenable-Title\", keenableTitle)\n\tif p.apiKey != \"\" {\n\t\treq.Header.Set(\"X-API-Key\", p.apiKey)\n\t}\n\n\tresp, err := p.client.Do(req)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to execute request: %w\", err)\n\t}\n\tdefer resp.Body.Close()\n\n\tif resp.StatusCode != http.StatusOK {\n\t\trespBody, _ := io.ReadAll(resp.Body)\n\t\tlogger.Warnf(ctx, \"[WebSearch][Keenable] API returned status %d: %s\", resp.StatusCode, string(respBody))\n\t\treturn nil, fmt.Errorf(\"keenable API returned status %d: %s\", resp.StatusCode, string(respBody))","sourceCodeStart":71,"sourceCodeEnd":107,"githubUrl":"https://github.com/Tencent/WeKnora/blob/988cbb03305e055d8ebb7d46d9ac6cc0803cd074/internal/infrastructure/web_search/keenable.go#L71-L107","documentation":"KeenableProvider.Search failed to construct the outbound http.Request via http.NewRequestWithContext for its POST to baseURL+path. This wraps errors such as an invalid URL (unsupported scheme, unparseable endpoint) or a nil/invalid context.","triggerScenarios":"http.NewRequestWithContext returns an error — typically because baseURL is malformed (missing scheme, invalid characters, bad URL) or ctx is nil.","commonSituations":"Misconfigured keenable base URL in config (e.g. 'keenable.example.com' without https://); stray whitespace or newline in configured URL; context constructed incorrectly and passed as nil.","solutions":["Log the full endpoint URL (it is already in the preceding log line) and validate the scheme is http/https.","Fix the configured base URL — prepend https:// and trim whitespace/newlines.","Ensure a non-nil context.Context is passed into Search.","Add URL parsing validation at provider construction time to fail early."],"exampleFix":"// before\nbaseURL: cfg.KeenableURL // \"keenable.example.com\"\n// after\nu, err := url.Parse(cfg.KeenableURL)\nif err != nil || u.Scheme == \"\" {\n    return nil, fmt.Errorf(\"invalid keenable URL: %q\", cfg.KeenableURL)\n}\nbaseURL: strings.TrimRight(cfg.KeenableURL, \"/\"),","handlingStrategy":"validation","validationCode":"u, err := url.Parse(cfg.KeenableBaseURL)\nif err != nil || (u.Scheme != \"http\" && u.Scheme != \"https\") || u.Host == \"\" {\n    return errors.New(\"invalid keenable base URL: must be absolute http(s) URL\")\n}","typeGuard":null,"tryCatchPattern":"if err != nil && strings.Contains(err.Error(), \"failed to create request\") {\n    log.Errorf(\"keenable endpoint URL invalid: %v\", err)\n    return nil, fmt.Errorf(\"check keenable base URL configuration: %w\", err)\n}","preventionTips":["Validate configured base URLs (scheme + host) at startup","Trim whitespace/newlines from URL config values","Use url.JoinPath or explicit path constants instead of string concatenation drift","Log the fully assembled endpoint before each request"],"tags":["http","url","keenable","web-search","request-construction"],"backgroundTag":"invalid-url","analyzedSha":"988cbb03305e055d8ebb7d46d9ac6cc0803cd074","analyzedAt":"2026-09-02T14:41:08.344Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}