{"record":{"id":"a0a125bb8390a386","repo":"Tencent/WeKnora","slug":"failed-to-create-request-w-a0a125","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/searxng.go","lineNumber":119,"sourceCode":"\tif maxResults <= 0 {\n\t\tmaxResults = 5\n\t}\n\n\tq := url.Values{}\n\tq.Set(\"q\", query)\n\tq.Set(\"format\", \"json\")\n\t// Use \"all\" (SearXNG's documented value for \"no language filter\") instead\n\t// of \"auto\", which is a UI-side default and not a valid /search parameter.\n\t// safesearch is intentionally not set here so the value configured in the\n\t// instance's settings.yml is honored.\n\tq.Set(\"language\", \"all\")\n\n\treqURL := p.baseURL + \"/search?\" + q.Encode()\n\tlogger.Infof(ctx, \"[WebSearch][SearXNG] query=%q maxResults=%d url=%s\", query, maxResults, p.baseURL)\n\n\treq, err := http.NewRequestWithContext(ctx, http.MethodGet, reqURL, nil)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to create request: %w\", err)\n\t}\n\treq.Header.Set(\"Accept\", \"application/json\")\n\treq.Header.Set(\"User-Agent\", \"WeKnora/1.0\")\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\tbody, _ := io.ReadAll(io.LimitReader(resp.Body, 1024))\n\t\treturn nil, fmt.Errorf(\"searxng returned status %d: %s\", resp.StatusCode, string(body))\n\t}\n\n\tvar data searxngResponse\n\tif err := json.NewDecoder(resp.Body).Decode(&data); err != nil {\n\t\tp.lastUnresponsive = nil","sourceCodeStart":101,"sourceCodeEnd":137,"githubUrl":"https://github.com/Tencent/WeKnora/blob/988cbb03305e055d8ebb7d46d9ac6cc0803cd074/internal/infrastructure/web_search/searxng.go#L101-L137","documentation":"http.NewRequestWithContext failed while constructing the GET request to the SearXNG /search endpoint. This means the request was never sent. In practice this fires when the composed URL (p.baseURL + \"/search?\" + encoded query) is malformed for Go's url.Parse, or the context is invalid.","triggerScenarios":"baseURL containing characters invalid in a URL (spaces, control chars, unencoded braces) that survive url.Values encoding in the query but break the base; an already-canceled/invalid context is rare but also returns an error here.","commonSituations":"Tenant config holding an untrimmed or quoted base_url like \"https://searxng.example.com/ \" or \"\\\"https://searxng.example.com\\\"\"; interpolation bugs leaving template placeholders in the URL.","solutions":["Log/inspect the wrapped error and the reqURL actually built; fix the baseURL in provider parameters","url.Parse the baseURL yourself at construction time (ValidateSearxngBaseURL should catch most of these earlier)","Trim whitespace and strip surrounding quotes from configured URLs","Check the context passed to Search — ensure it is a live context.Background()-derived context"],"exampleFix":"// before\nbaseURL := \"https://searxng.example.com/ \" // trailing space\n// after\nbaseURL := strings.TrimSpace(strings.Trim(cfg.BaseURL, \"\\\"'\"))","handlingStrategy":"validation","validationCode":"if _, err := url.Parse(baseURL); err != nil {\n    return fmt.Errorf(\"invalid searxng base_url: %w\", err)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Trim and de-quote configured URLs","url.Parse the base URL at construction time","Avoid template placeholders in config without expansion"],"tags":["http","url-malformed","searxng","request-construction"],"backgroundTag":"malformed-url","analyzedSha":"988cbb03305e055d8ebb7d46d9ac6cc0803cd074","analyzedAt":"2026-09-02T14:41:08.344Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}