{"record":{"id":"8d5ff239b928b105","repo":"Tencent/WeKnora","slug":"failed-to-create-request-w-8d5ff2","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/tavily.go","lineNumber":80,"sourceCode":"\tif len(query) == 0 {\n\t\treturn nil, fmt.Errorf(\"query is empty\")\n\t}\n\tlogger.Infof(ctx, \"[WebSearch][Tavily] query=%q maxResults=%d url=%s\", query, maxResults, p.baseURL)\n\n\treqBody := tavilySearchRequest{\n\t\tAPIKey:     p.apiKey,\n\t\tQuery:      query,\n\t\tMaxResults: maxResults,\n\t}\n\n\tbodyBytes, err := json.Marshal(reqBody)\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\", p.baseURL, 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\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][Tavily] API returned status %d: %s\", resp.StatusCode, string(respBody))\n\t\treturn nil, fmt.Errorf(\"tavily API returned status %d: %s\", resp.StatusCode, string(respBody))\n\t}\n\n\trespBody, err := io.ReadAll(resp.Body)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to read response: %w\", err)","sourceCodeStart":62,"sourceCodeEnd":98,"githubUrl":"https://github.com/Tencent/WeKnora/blob/988cbb03305e055d8ebb7d46d9ac6cc0803cd074/internal/infrastructure/web_search/tavily.go#L62-L98","documentation":"http.NewRequestWithContext failed constructing the POST request to the Tavily API endpoint. The request never left the process. Practically this means p.baseURL is not a parseable URL (malformed/whitespace/placeholder text) or the context is already invalid.","triggerScenarios":"baseURL configured as an invalid URL string (spaces, control characters, \"localhost:99999\" bad port, unescaped characters) or an unfilled template placeholder; corrupted context value.","commonSituations":"Config typo in the Tavily endpoint override; env-substitution leaving \"${TAVILY_URL}\" literal in the config; trailing whitespace/newline from env file parsing.","solutions":["Log the wrapped error and p.baseURL; fix the endpoint value in configuration","url.Parse(p.baseURL) in the constructor/validate step to fail fast with a clearer message","Trim whitespace and expand env placeholders (${VAR}) before storing baseURL","Confirm the context passed to Search is valid and not already canceled"],"exampleFix":"// before\nbaseURL := \"${TAVILY_URL}\" // unexpanded placeholder\n// after\nbaseURL := os.ExpandEnv(strings.TrimSpace(cfg.TavilyURL))\nif _, err := url.Parse(baseURL); err != nil {\n    return nil, fmt.Errorf(\"invalid tavily base URL: %w\", err)\n}","handlingStrategy":"validation","validationCode":"if _, err := url.Parse(baseURL); err != nil {\n    return fmt.Errorf(\"invalid tavily base URL: %w\", err)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["url.Parse the endpoint at construction time for fast, clear failures","Expand env placeholders and trim whitespace in config values","Avoid overriding baseURL unless necessary; use the default endpoint"],"tags":["http","url-malformed","tavily","request-construction","config"],"backgroundTag":"malformed-url","analyzedSha":"988cbb03305e055d8ebb7d46d9ac6cc0803cd074","analyzedAt":"2026-09-02T14:41:08.344Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}