thanos-io/thanos · error
parse alert query url
Error message
parse alert query url
What it means
After parsing labels, the rule command parses --alertmanagers.url (alertQueryURL) with net/url.Parse. This wraps the parse error when the URL string is malformed and aborts startup, since the alert manager client cannot be built from an invalid URL.
Solutions
- URL-encode the value and remove whitespace: --alertmanagers.url=http://alertmanager:9093.
- Quote the flag in the shell/Helm values so spaces or pipes are not interpreted.
- Verify each URL parses with a quick script (python -c "import urllib.parse;urllib.parse.urlparse('...')").
- If using multiple URLs, ensure each entry in --alertmanagers.url is individually valid.
Example fix
// before thanos rule --alertmanagers.url=http://alert manager:9093 // after thanos rule --alertmanagers.url=http://alertmanager:9093
Defensive patterns
Strategy: validation
Validate before calling
from urllib.parse import urlparse
def check_alertmanager_url(u):
p = urlparse(u)
if p.scheme not in ("http", "https") or not p.netloc or any(c.isspace() for c in u):
raise SystemExit(f"invalid --alertmanagers.url: {u!r}")
return u Type guard
def is_valid_url(u):
from urllib.parse import urlparse
try:
p = urlparse(u)
return bool(p.scheme in ("http", "https") and p.netloc)
except (ValueError, AttributeError):
return False Prevention
- Validate URLs in Helm values with schema checks before deploy.
- Never leave raw spaces or unencoded '%' in URLs.
- Quote all URL flags in shell/systemd units.
- One URL per flag occurrence when passing multiple alertmanagers.
When it happens
Trigger: url.Parse(*conf.alertmgr.alertQueryURL) returns an error for strings with invalid characters (spaces, unescaped control chars) or grossly malformed schemes that url.Parse rejects (e.g. 'http://al ert:9093' or '://host').
Common situations: Space in the URL from a YAML list split across lines; unencoded special characters like % or | in the host; forgetting the scheme combined with odd syntax; shell quoting mangling the value.
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
- parse labels
- no query configuration parameter was given
- --query/--query.sd-files/--grpc-query-endpoint and…
- level is bigger then default set of
- unknown sync strategy
AI-assisted analysis of thanos-io/thanos@35b8b99117 (2026-09-07).
Data as JSON: /api/errors/2fd5f1b75530a77d.
Report an issue: GitHub.
Appendix: source
Thrown at cmd/thanos/rule.go:196
"(Deprecated) Enables the ingestion of native histograms. This flag is a no-op now and will be removed in the future. Native histogram ingestion is always enabled.").
Default("true").BoolVar(&conf.tsdbEnableNativeHistograms)
conf.rwConfig = extflag.RegisterPathOrContent(cmd, "remote-write.config", "YAML config for the remote-write configurations, that specify servers where samples should be sent to (see https://prometheus.io/docs/prometheus/latest/configuration/configuration/#remote_write). This automatically enables stateless mode for ruler and no series will be stored in the ruler's TSDB. If an empty config (or file) is provided, the flag is ignored and ruler is run with its own TSDB.", extflag.WithEnvSubstitution())
conf.objStoreConfig = extkingpin.RegisterCommonObjStoreFlags(cmd, "", false)
reqLogConfig := extkingpin.RegisterRequestLoggingFlags(cmd)
var err error
cmd.Setup(func(g *run.Group, logger log.Logger, reg *prometheus.Registry, tracer opentracing.Tracer, reload <-chan struct{}, _ bool) error {
conf.lset, err = parseFlagLabels(*labelStrs)
if err != nil {
return errors.Wrap(err, "parse labels")
}
conf.alertQueryURL, err = url.Parse(*conf.alertmgr.alertQueryURL)
if err != nil {
return errors.Wrap(err, "parse alert query url")
}
tsdbOpts := &tsdb.Options{
MinBlockDuration: int64(time.Duration(*tsdbBlockDuration) / time.Millisecond),
MaxBlockDuration: int64(time.Duration(*tsdbBlockDuration) / time.Millisecond),
RetentionDuration: int64(time.Duration(*tsdbRetention) / time.Millisecond),
NoLockfile: *noLockFile,
WALCompression: compressutil.ParseCompressionType(*walCompression, compression.Snappy),
}
agentOpts := &agent.Options{
WALCompression: compressutil.ParseCompressionType(*walCompression, compression.Snappy),
NoLockfile: *noLockFile,
}
// Parse and check query configuration.
lookupQueries := map[string]struct{}{}
for _, q := range conf.query.addrs {View on GitHub (pinned to 35b8b99117)