{"record":{"id":"1e9b7bd07fee5629","repo":"vxcontrol/pentagi","slug":"failed-to-build-request-v-1e9b7b","errorCode":null,"errorMessage":"failed to build request: %v","messagePattern":"failed to build request: (.+?)","errorType":"exception","errorClass":"Fatal","httpStatus":null,"severity":"error","filePath":"backend/pkg/tools/searchers/tavily.go","lineNumber":126,"sourceCode":"\n\treqPayload := tavilyRequest{\n\t\tQuery:             query,\n\t\tApiKey:            t.apiKey(),\n\t\tTopic:             \"general\",\n\t\tSearchDepth:       \"advanced\",\n\t\tIncludeImages:     false,\n\t\tIncludeAnswer:     true,\n\t\tIncludeRawContent: true,\n\t\tMaxResults:        maxResults,\n\t}\n\treqBody, err := json.Marshal(reqPayload)\n\tif err != nil {\n\t\treturn \"\", Fatal(fmt.Errorf(\"failed to marshal request body: %v\", err))\n\t}\n\n\treq, err := http.NewRequest(http.MethodPost, tavilyURL, bytes.NewBuffer(reqBody))\n\tif err != nil {\n\t\treturn \"\", Fatal(fmt.Errorf(\"failed to build request: %v\", err))\n\t}\n\n\treq = req.WithContext(ctx)\n\treq.Header.Set(\"Content-Type\", \"application/json\")\n\n\tresp, err := client.Do(req)\n\tif err != nil {\n\t\treturn \"\", Retryable(fmt.Errorf(\"failed to do request: %v\", err), 0)\n\t}\n\tdefer resp.Body.Close()\n\n\treturn t.parseHTTPResponse(ctx, resp)\n}\n\nfunc (t *tavily) parseHTTPResponse(ctx context.Context, resp *http.Response) (string, error) {\n\tswitch resp.StatusCode {\n\tcase http.StatusOK:\n\t\tvar respBody tavilySearchResult","sourceCodeStart":108,"sourceCodeEnd":144,"githubUrl":"https://github.com/vxcontrol/pentagi/blob/ea665308baaff015b226f308438a68d929d0f29b/backend/pkg/tools/searchers/tavily.go#L108-L144","documentation":"http.NewRequest(http.MethodPost, tavilyURL, body) failed to construct the request — tavilyURL failed url.Parse or the body reader was invalid; the searcher returns a Fatal error. The context is attached afterwards via req.WithContext(ctx), so this error is purely about URL/body construction.","triggerScenarios":"search() builds the request to the package-constant tavilyURL; fires only when tavilyURL is malformed (e.g. typo in scheme/control chars) or refactoring replaces the constant with a bad dynamic value.","commonSituations":"Editing the tavilyURL constant with a typo (\"https:/api.tavily.com/search\" — missing slash, whitespace, or newline picked up from config).","solutions":["Read the parse error in the wrapped message and fix the tavilyURL constant","Ensure scheme is https:// and the URL has no whitespace/newlines","If the URL becomes configurable, validate it at startup rather than failing per-request"],"exampleFix":"// before\nconst tavilyURL = \"https://api.tavily.com/search \" // trailing space\n// after\nconst tavilyURL = \"https://api.tavily.com/search\"","handlingStrategy":"validation","validationCode":"if u, err := url.Parse(tavilyURL); err != nil || u.Scheme != \"https\" {\n    log.Fatalf(\"invalid tavily URL: %v\", err)\n}","typeGuard":null,"tryCatchPattern":"req, err := http.NewRequest(http.MethodPost, tavilyURL, bytes.NewBuffer(reqBody))\nif err != nil {\n    return \"\", Fatal(fmt.Errorf(\"failed to build request: %v\", err))\n}","preventionTips":["Validate endpoint URL constants in tests at package init","Trim any dynamically loaded URL values of whitespace/newlines","Use http.NewRequestWithContext directly instead of attaching ctx later"],"tags":["http-request","url-parsing","tavily","go"],"backgroundTag":"invalid-url-format","analyzedSha":"ea665308baaff015b226f308438a68d929d0f29b","analyzedAt":"2026-09-01T14:16:31.421Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}