vxcontrol/pentagi · error · Fatal
invalid searxng base URL: %w
Error message
invalid searxng base URL: %w
What it means
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.
Source
Thrown at backend/pkg/tools/searchers/searxng.go:83
langfuse.WithEventMetadata(langfuse.Metadata{
"engine": "searxng",
"query": req.Query,
"max_results": req.MaxResults,
"error": err.Error(),
}),
)
obs.LogErrorOrCancel(logger, err, "failed to search in searxng")
return "", err
}
return result, nil
}
func (s *searxng) search(ctx context.Context, query string, maxResults int) (string, error) {
apiURL, err := url.Parse(s.baseURL())
if err != nil {
return "", Fatal(fmt.Errorf("invalid searxng base URL: %w", err))
}
if !strings.HasSuffix(apiURL.Path, "/search") {
apiURL.Path = strings.TrimSuffix(apiURL.Path, "/") + "/search"
}
params := url.Values{}
params.Add("q", query)
params.Add("format", "json")
params.Add("language", s.language())
params.Add("categories", s.categories())
params.Add("safesearch", s.safeSearch())
if timeRange := s.timeRange(); timeRange != "" {
params.Add("time_range", timeRange)
}
if maxResults > 0 {View on GitHub (pinned to ea665308ba)
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
Example fix
// before (.env) SEARXNG_URL=http://searxng:8080/search # after (.env) SEARXNG_URL=http://searxng:8080
Defensive patterns
Strategy: validation
Validate before calling
// validate at startup
srv, err := url.Parse(os.Getenv("SEARXNG_URL"))
if err != nil || srv.Scheme == "" || srv.Host == "" {
log.Fatalf("invalid SEARXNG_URL %q: %v", os.Getenv("SEARXNG_URL"), err)
} Type guard
func validHTTPURL(raw string) bool {
u, err := url.Parse(raw)
return err == nil && (u.Scheme == "http" || u.Scheme == "https") && u.Host != ""
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- failed to build request: %v
- failed to create http client: %w
- failed to create request: %w
- unexpected status code: %d
- token validation disabled with default salt
AI-assisted analysis of vxcontrol/pentagi@ea665308ba (2026-09-01).
Data as JSON: /api/errors/bf195ebfd778a824.
Report an issue: GitHub.