{"record":{"id":"e99a8bd55fa52a59","repo":"vxcontrol/pentagi","slug":"failed-to-create-request-w-e99a8b","errorCode":null,"errorMessage":"failed to create request: %w","messagePattern":"failed to create request: %w","errorType":"exception","errorClass":"Fatal","httpStatus":null,"severity":"error","filePath":"backend/pkg/tools/searchers/searxng.go","lineNumber":118,"sourceCode":"\n\tif maxResults > 0 {\n\t\tparams.Add(\"limit\", strconv.Itoa(maxResults))\n\t} else {\n\t\tparams.Add(\"limit\", \"10\")\n\t}\n\n\tapiURL.RawQuery = params.Encode()\n\n\tclient, err := system.GetHTTPClient(s.cfg)\n\tif err != nil {\n\t\treturn \"\", Fatal(fmt.Errorf(\"failed to create http client: %w\", err))\n\t}\n\n\tclient.Timeout = s.timeout()\n\n\treq, err := http.NewRequestWithContext(ctx, http.MethodGet, apiURL.String(), nil)\n\tif err != nil {\n\t\treturn \"\", Fatal(fmt.Errorf(\"failed to create request: %w\", err))\n\t}\n\n\treq.Header.Set(\"User-Agent\", \"PentAGI/1.0\")\n\n\tresp, err := client.Do(req)\n\tif err != nil {\n\t\treturn \"\", Retryable(fmt.Errorf(\"failed to do request: %w\", err), 0)\n\t}\n\tdefer resp.Body.Close()\n\n\treturn s.parseHTTPResponse(resp, query)\n}\n\nfunc (s *searxng) parseHTTPResponse(resp *http.Response, query string) (string, error) {\n\tif resp.StatusCode != http.StatusOK {\n\t\terr := fmt.Errorf(\"unexpected status code: %d\", resp.StatusCode)\n\t\tif resp.StatusCode == http.StatusTooManyRequests || resp.StatusCode >= 500 {\n\t\t\treturn \"\", Retryable(err, 0)","sourceCodeStart":100,"sourceCodeEnd":136,"githubUrl":"https://github.com/vxcontrol/pentagi/blob/ea665308baaff015b226f308438a68d929d0f29b/backend/pkg/tools/searchers/searxng.go#L100-L136","documentation":"http.NewRequestWithContext failed while constructing the GET request to the SearxNG endpoint. This wraps Go's standard library error and is classified Fatal. With a URL already validated by url.Parse earlier, this is nearly impossible to hit in practice — it can only occur if the serialized URL (after appending /search and query params) becomes invalid, e.g. contains a NUL byte.","triggerScenarios":"The base URL string contains a NUL byte (\\x00) or other control character that url.Parse accepted but NewRequestWithContext rejects via url.ParseRequestURI; ctx already canceled does NOT trigger this (that fails at client.Do).","commonSituations":"Env var polluted with a NUL byte from bad shell templating or binary-joined config strings; pathological SEARXNG_URL values surviving url.Parse.","solutions":["Inspect the final apiURL.String() value in logs for control characters and sanitize the SEARXNG_URL env","Strip control characters from the configured URL before parsing (strings.Map with unicode.IsPrint filter)","Fix the source of the corrupted value in .env, docker-compose.yml, or secrets injection","This is Fatal — no retry will occur; restart with corrected configuration","If persistent, add a startup-time validation of SEARXNG_URL so misconfiguration fails fast at boot"],"exampleFix":"// before\nreq, err := http.NewRequestWithContext(ctx, http.MethodGet, apiURL.String(), nil)\n// after\ncleanURL := strings.Map(func(r rune) rune {\n    if r == 0 || !unicode.IsPrint(r) { return -1 }\n    return r\n}, apiURL.String())\nreq, err := http.NewRequestWithContext(ctx, http.MethodGet, cleanURL, nil)\n","handlingStrategy":"validation","validationCode":"// sanitize and validate before request construction\nu := strings.Map(func(r rune) rune { if r == 0 || !unicode.IsPrint(r) { return -1 }; return r }, baseURL)\nif _, err := url.ParseRequestURI(u); err != nil {\n    return fmt.Errorf(\"unusable searxng URL %q: %w\", u, err)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Reject NUL/control bytes in env-configured URLs at boot","Prefer standard env templating (compose variable substitution) over shell string concatenation","Log the final request URL (without secrets) when this error fires","Validate config early so this Fatal error never appears mid-flow"],"tags":["http","url","searxng","request-construction"],"backgroundTag":"invalid-url-config","analyzedSha":"ea665308baaff015b226f308438a68d929d0f29b","analyzedAt":"2026-09-01T14:16:31.421Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}