{"record":{"id":"bf195ebfd778a824","repo":"vxcontrol/pentagi","slug":"invalid-searxng-base-url-w","errorCode":null,"errorMessage":"invalid searxng base URL: %w","messagePattern":"invalid searxng base URL: %w","errorType":"exception","errorClass":"Fatal","httpStatus":null,"severity":"error","filePath":"backend/pkg/tools/searchers/searxng.go","lineNumber":83,"sourceCode":"\t\t\tlangfuse.WithEventMetadata(langfuse.Metadata{\n\t\t\t\t\"engine\":      \"searxng\",\n\t\t\t\t\"query\":       req.Query,\n\t\t\t\t\"max_results\": req.MaxResults,\n\t\t\t\t\"error\":       err.Error(),\n\t\t\t}),\n\t\t)\n\n\t\tobs.LogErrorOrCancel(logger, err, \"failed to search in searxng\")\n\t\treturn \"\", err\n\t}\n\n\treturn result, nil\n}\n\nfunc (s *searxng) search(ctx context.Context, query string, maxResults int) (string, error) {\n\tapiURL, err := url.Parse(s.baseURL())\n\tif err != nil {\n\t\treturn \"\", Fatal(fmt.Errorf(\"invalid searxng base URL: %w\", err))\n\t}\n\n\tif !strings.HasSuffix(apiURL.Path, \"/search\") {\n\t\tapiURL.Path = strings.TrimSuffix(apiURL.Path, \"/\") + \"/search\"\n\t}\n\n\tparams := url.Values{}\n\tparams.Add(\"q\", query)\n\tparams.Add(\"format\", \"json\")\n\tparams.Add(\"language\", s.language())\n\tparams.Add(\"categories\", s.categories())\n\tparams.Add(\"safesearch\", s.safeSearch())\n\n\tif timeRange := s.timeRange(); timeRange != \"\" {\n\t\tparams.Add(\"time_range\", timeRange)\n\t}\n\n\tif maxResults > 0 {","sourceCodeStart":65,"sourceCodeEnd":101,"githubUrl":"https://github.com/vxcontrol/pentagi/blob/ea665308baaff015b226f308438a68d929d0f29b/backend/pkg/tools/searchers/searxng.go#L65-L101","documentation":"The SearxNG searcher parses the configured base URL (cfg.SearxngURL) with net/url.Parse before appending /search and issuing the query. If the URL cannot be parsed, the search aborts with a Fatal error (no retry). Note that Go's url.Parse is very permissive and almost never errors, so hitting this usually means control characters or a severely malformed value in the configuration.","triggerScenarios":"SEARXNG_URL contains invalid characters (spaces, raw control characters, unescaped non-ASCII in unusual positions) or a corrupted value from env interpolation, e.g. SEARXNG_URL=\"http://searxng:8080\\n\" or a value containing an unescaped newline.","commonSituations":"Misconfigured docker-compose env with accidental whitespace/newline in SEARXNG_URL; secrets templating tools injecting malformed values; copy-paste of a URL with invisible Unicode characters.","solutions":["Print/verify the SEARXNG_URL env value and fix malformed characters (use a plain URL like http://searxng:8080)","Validate the URL manually: url.Parse('your-value') in a scratch Go program to reproduce the exact parse error","Check .env / docker-compose.yml for line-continuation or quoting issues that corrupt the value","Restart the container after fixing the env so the config is re-read","Note the error is Fatal — the orchestrator will fall back to other engines only if a fallback chain is configured"],"exampleFix":"// before (.env)\nSEARXNG_URL=http://searxng:8080/search\n   \n# after (.env)\nSEARXNG_URL=http://searxng:8080\n","handlingStrategy":"validation","validationCode":"// validate at startup\nsrv, err := url.Parse(os.Getenv(\"SEARXNG_URL\"))\nif err != nil || srv.Scheme == \"\" || srv.Host == \"\" {\n    log.Fatalf(\"invalid SEARXNG_URL %q: %v\", os.Getenv(\"SEARXNG_URL\"), err)\n}","typeGuard":"func validHTTPURL(raw string) bool {\n    u, err := url.Parse(raw)\n    return err == nil && (u.Scheme == \"http\" || u.Scheme == \"https\") && u.Host != \"\"\n}","tryCatchPattern":null,"preventionTips":["Fail fast: validate SEARXNG_URL at config-load/boot time, not at first search","Avoid env values with trailing whitespace/newlines; quote carefully in .env and compose files","Use simple values without embedded control characters","Test engine availability (curl the URL) after deployment changes"],"tags":["url","configuration","searxng"],"backgroundTag":"invalid-url-config","analyzedSha":"ea665308baaff015b226f308438a68d929d0f29b","analyzedAt":"2026-09-01T14:16:31.421Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}