{"record":{"id":"2485618480906dd4","repo":"Tencent/WeKnora","slug":"failed-to-create-exa-request-w","errorCode":null,"errorMessage":"failed to create Exa request: %w","messagePattern":"failed to create Exa request: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/infrastructure/web_search/exa.go","lineNumber":89,"sourceCode":"\t}\n\tif maxResults > maxExaResults {\n\t\tmaxResults = maxExaResults\n\t}\n\n\tbodyBytes, err := json.Marshal(exaSearchRequest{\n\t\tQuery:      query,\n\t\tNumResults: maxResults,\n\t\tContents: exaContents{\n\t\t\tHighlights: true,\n\t\t\tText:       p.includeText,\n\t\t},\n\t})\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to marshal Exa request: %w\", err)\n\t}\n\treq, err := http.NewRequestWithContext(ctx, http.MethodPost, p.baseURL, bytes.NewReader(bodyBytes))\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to create Exa request: %w\", err)\n\t}\n\treq.Header.Set(\"Content-Type\", \"application/json\")\n\treq.Header.Set(\"x-api-key\", p.apiKey)\n\n\tlogger.Infof(ctx, \"[WebSearch][Exa] query=%q maxResults=%d url=%s\", query, maxResults, p.baseURL)\n\tresp, err := p.client.Do(req)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to execute Exa request: %w\", err)\n\t}\n\tdefer resp.Body.Close()\n\tbody, err := io.ReadAll(io.LimitReader(resp.Body, maxExaResponseBytes))\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to read Exa response: %w\", err)\n\t}\n\tif resp.StatusCode < http.StatusOK || resp.StatusCode >= http.StatusMultipleChoices {\n\t\tlogger.Warnf(ctx, \"[WebSearch][Exa] API returned status %d: %s\", resp.StatusCode, string(body))\n\t\treturn nil, fmt.Errorf(\"exa API returned status %d: %s\", resp.StatusCode, string(body))\n\t}","sourceCodeStart":71,"sourceCodeEnd":107,"githubUrl":"https://github.com/Tencent/WeKnora/blob/988cbb03305e055d8ebb7d46d9ac6cc0803cd074/internal/infrastructure/web_search/exa.go#L71-L107","documentation":"Wraps errors from http.NewRequestWithContext when constructing the POST request to the Exa API. Given a constant http.MethodPost and a configured baseURL, failures indicate the configured base URL is not a valid URL or the context is invalid.","triggerScenarios":"Calling Search when p.baseURL is malformed (bad config/default override) or ctx passed into Search is already canceled/invalid.","commonSituations":"A config override set baseURL to a garbage value, missing scheme in a custom endpoint, or an upstream canceled context propagated into Search.","solutions":["Verify p.baseURL is a valid absolute http(s) URL (log it on failure)","Ensure the context passed to Search is valid and not pre-canceled","Compare the configured base URL against the official Exa endpoint https://api.exa.ai/search","Unwrap the %w error for the exact url.Parse failure"],"exampleFix":"// before\nreq, err := http.NewRequestWithContext(ctx, http.MethodPost, p.baseURL, bytes.NewReader(bodyBytes))\n// after\nu, perr := url.Parse(p.baseURL)\nif perr != nil || u.Scheme == \"\" || u.Host == \"\" {\n    return nil, fmt.Errorf(\"invalid exa baseURL %q: %w\", p.baseURL, perr)\n}\nreq, err := http.NewRequestWithContext(ctx, http.MethodPost, p.baseURL, bytes.NewReader(bodyBytes))","handlingStrategy":"validation","validationCode":"u, err := url.Parse(cfg.ExaBaseURL)\nif err != nil || u.Scheme == \"\" || u.Host == \"\" {\n    return fmt.Errorf(\"invalid exa base URL %q\", cfg.ExaBaseURL)\n}\nif err := ctx.Err(); err != nil {\n    return err\n}","typeGuard":null,"tryCatchPattern":"results, err := provider.Search(ctx, query, 10, false)\nif err != nil {\n    if errors.Is(err, context.Canceled) {\n        return nil, fmt.Errorf(\"search canceled: %w\", err)\n    }\n    return nil, err\n}","preventionTips":["Validate the base URL at provider construction, not per-request","Use the official endpoint https://api.exa.ai/search as the default","Check context validity before dispatching long search operations"],"tags":["http","request-construction","url","config","go"],"backgroundTag":"http-request-construction-failed","analyzedSha":"988cbb03305e055d8ebb7d46d9ac6cc0803cd074","analyzedAt":"2026-09-02T14:41:08.344Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}