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

  1. URL-encode the value and remove whitespace: --alertmanagers.url=http://alertmanager:9093.
  2. Quote the flag in the shell/Helm values so spaces or pipes are not interpreted.
  3. Verify each URL parses with a quick script (python -c "import urllib.parse;urllib.parse.urlparse('...')").
  4. 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

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


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)