thanos-io/thanos · error
alertmanagers.url contains empty scheme
Error message
alertmanagers.url contains empty scheme
What it means
BuildAlertmanagerConfig parses the alertmanagers.url and requires a URL scheme (http/https, or a dns-prefixed scheme like dns+http). An empty scheme means the URL was relative or malformed, so no HTTP client can be constructed.
Solutions
- Prefix the URL with its scheme: use http://alertmanager:9093 (or https://...).
- If the scheme must include DNS discovery, use the dns+http:// prefix form.
- Add config validation/linting before startup to catch scheme-less URLs.
Example fix
// before url: alertmanager.monitoring:9093 // after url: http://alertmanager.monitoring:9093
Defensive patterns
Strategy: validation
Validate before calling
u, err := url.Parse(cfg.URL)
if err != nil || u.Scheme == "" {
return fmt.Errorf("alertmanagers.url %q must include a scheme, e.g. http://host:9093", cfg.URL)
} Prevention
- Always write Alertmanager URLs with explicit http:// or https://
- Validate all URLs with net/url.Parse at config load time
- Template-render configs and re-validate after substitution
When it happens
Trigger: alertmanagers.sd_configs/static_configs url like "alertmanager:9093" or ":9093" passed to BuildAlertmanagerConfig (called from runRule); url.Parse succeeds but parsed.Scheme is empty.
Common situations: Omitting http:// when writing the Alertmanager URL in rule/ruler config; config templating that renders an empty scheme prefix; port-only addresses copied from docker-compose.
Understand the failure class
Background: "Invalid URL" errors: why new URL(), URI.parse, and reqwest::Url reject your string — missing scheme, whitespace, and bad path format — this error's family across 39 libraries.
Related errors
- alertmanagers.url contains empty host
- setup downstream roundtripper
- parse alert query url
- --alertmanagers.url and --alertmanagers.config* parameters…
- invalid Alertmanager API version
AI-assisted analysis of thanos-io/thanos@35b8b99117 (2026-09-07).
Data as JSON: /api/errors/62f7e1a8ae7df910.
Report an issue: GitHub.
Appendix: source
Thrown at pkg/alert/config.go:99
// LoadAlertingConfig loads a list of AlertmanagerConfig from YAML data.
func LoadAlertingConfig(confYaml []byte) (AlertingConfig, error) {
var cfg AlertingConfig
if err := yaml.UnmarshalStrict(confYaml, &cfg); err != nil {
return cfg, err
}
return cfg, nil
}
// BuildAlertmanagerConfig initializes and returns an Alertmanager client configuration from a static address.
func BuildAlertmanagerConfig(address string, timeout time.Duration) (AlertmanagerConfig, error) {
parsed, err := url.Parse(address)
if err != nil {
return AlertmanagerConfig{}, err
}
scheme := parsed.Scheme
if scheme == "" {
return AlertmanagerConfig{}, errors.New("alertmanagers.url contains empty scheme")
}
host := parsed.Host
if host == "" {
return AlertmanagerConfig{}, errors.New("alertmanagers.url contains empty host")
}
for _, qType := range []dns.QType{dns.A, dns.SRV, dns.SRVNoA} {
prefix := string(qType) + "+"
if strings.HasPrefix(strings.ToLower(scheme), prefix) {
// Scheme is of the form "<dns type>+<http scheme>".
scheme = strings.TrimPrefix(scheme, prefix)
host = prefix + parsed.Host
if qType == dns.A {
if _, _, err := net.SplitHostPort(parsed.Host); err != nil {
// The host port could be missing. Append the defaultAlertmanagerPort.
host = host + ":" + strconv.Itoa(defaultAlertmanagerPort)
}View on GitHub (pinned to 35b8b99117)