Billionmail/BillionMail · error
base URL not configured
Error message
base URL not configured
What it means
HttpGetSrc in public/common.go performs an HTTP GET and, for any status code outside 2xx (or <200), records an error formatted as 'http get error: %s' with resp.Status (e.g. '404 Not Found'). Note the function still proceeds to read the body; the error is returned with whatever body was read, so callers get a non-2xx response surfaced as a Go error.
Source
Thrown at core/internal/controller/campaign/campaign_v1_form.go:99
if err = r.Session.Set("csrf_token", csrfToken); err != nil {
csrfToken = ""
}
groups, _ := contact.GetAllGroups(ctx, "")
err = r.Response.WriteTpl("subscription_form.html", g.Map{
"Groups": groups,
"CSRFToken": csrfToken,
})
return
}
// sendConfirmationEmail sends a confirmation email to the newly subscribed user
func sendConfirmationEmail(ctx context.Context, email, name string) error {
// Get the base domain to construct noreply email
baseURL := domains.GetBaseURL()
if baseURL == "" {
return fmt.Errorf("base URL not configured")
}
// Extract domain from base URL
domain := ""
if u, err := url.Parse(baseURL); err == nil && u.Hostname() != "" {
domain = u.Hostname()
} else {
// Fallback: try to get from environment
if hostname, err := public.DockerEnv("BILLIONMAIL_HOSTNAME"); err == nil && hostname != "" {
domain = hostname
} else {
return fmt.Errorf("unable to determine domain for noreply email")
}
}
// Construct noreply email address
noreplyEmail := fmt.Sprintf("noreply@%s", domain)
View on GitHub (pinned to fc36c76c05)
Solutions
- Inspect resp.Status in the error to identify the concrete HTTP status and address it (fix URL, auth, or server)
- Verify the target URL is reachable (curl the endpoint) and correct any typos or port errors
- Add/refresh authentication credentials if the status is 401/403
- Enable redirect following or call the final URL directly for 3xx statuses; add retry/backoff for 5xx
Example fix
// before
body, err := public.HttpGetSrc(ctx, client, "http://host/old-endpoint")
// after
if body, err = public.HttpGetSrc(ctx, client, "https://host/new-endpoint"); err != nil {
g.Log().Errorf(ctx, "GET failed: %v", err)
return err
} Defensive patterns
Strategy: try-catch
Validate before calling
req, _ := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
if resp, err := client.Do(req); err == nil {
resp.Body.Close()
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
return fmt.Errorf("endpoint unhealthy: %s", resp.Status)
}
} Try / catch
body, err := public.HttpGetSrc(ctx, client, url)
if err != nil {
var he *fmt.Errorf // inspect status embedded in message
g.Log().Warningf(ctx, "GET %s failed: %v", url, err)
if strings.Contains(err.Error(), "50") { // 5xx: retry with backoff
return retryWithBackoff(url)
}
return err
} Prevention
- Check the target URL and credentials before automated calls
- Treat 4xx and 5xx differently: fix inputs for 4xx, retry with backoff for 5xx
- Set timeouts on the HTTP client so hangs fail fast
- Monitor upstream endpoints for moves (301/404) and update callers
When it happens
Trigger: Any call through HttpGetSrc (directly or via HttpRequestTool, RequestUrl, HttpGetJson) where the remote server returns 1xx, 3xx (unfollowed redirects), 4xx or 5xx — dead URL, auth failure, server error, redirect to a non-followed location.
Common situations: Calling an internal API with an expired token (401/403), fetching a moved endpoint (404), a downstream service being down (502/503), or a server returning 3xx with redirects disabled.
Related errors
- base URL accessibility test failed: %w
- unexpected API response: %d %s
- download file failed:
- circuit breaker [%s]: %w
- download lipsync video: %w
AI-assisted analysis of Billionmail/BillionMail@fc36c76c05 (2026-09-05).
Data as JSON: /api/errors/f5c42b55c249aebf.
Report an issue: GitHub.