thanos-io/thanos · error
downstream URL should be configured
Error message
downstream URL should be configured
What it means
The query-frontend acts as a proxy and forwards requests to a downstream Prometheus-compatible URL; Validate() requires cfg.DownstreamURL to be non-empty. Without it the frontend has nowhere to send uncached/split queries, so startup is aborted.
Solutions
- Set downstream_url in the query_frontend config block to the upstream Prometheus/Thanos query URL
- When using env expansion, ensure the environment variable is defined in the pod/container
- Verify the flag -query-frontend.downstream-url is passed if configuring via flags
- Point it at the correct scheme and address, e.g. http://thanos-query:9090
Example fix
// before query_frontend: split_queries_by_interval: 15m // after query_frontend: downstream_url: http://thanos-query:9090 split_queries_by_interval: 15m
Defensive patterns
Strategy: validation
Validate before calling
if cfg.DownstreamURL == "" {
return errors.New("query_frontend.downstream_url must be set")
}
if _, err := url.Parse(cfg.DownstreamURL); err != nil {
return fmt.Errorf("downstream_url malformed: %w", err)
} Type guard
func downstreamConfigured(cfg Config) bool { return cfg.DownstreamURL != "" } Try / catch
if err := cfg.Validate(); err != nil {
if strings.Contains(err.Error(), "downstream URL") {
log.Fatalf("configure -query-frontend.downstream-url: %v", err)
}
} Prevention
- Include downstream_url in the base config template for query-frontend deployments
- When using env expansion, add a readiness check that the env var is non-empty
- Point downstream at an internal service URL reachable from the frontend pods
When it happens
Trigger: Config.Validate is called with cfg.DownstreamURL == "" — the downstream_url (or -query-frontend.downstream-url flag) was not set, or was set to an empty string via env expansion.
Common situations: Minimal query-frontend deployments where operators enabled split/cache features but forgot the downstream target; environment-variable-based configs where DOWNSTREAM_URL is unset in the deployment environment; typos leaving the key under the wrong YAML block.
Understand the failure class
Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.
Related errors
- split queries or split threshold interval should be greater…
- invalid ResultsCache config for query_range tripperware
- split queries interval and dynamic query split interval…
- split queries interval should be greater than 0 when…
- invalid ResultsCache config for labels tripperware
AI-assisted analysis of thanos-io/thanos@35b8b99117 (2026-09-07).
Data as JSON: /api/errors/658fe9b266245072.
Report an issue: GitHub.
Appendix: source
Thrown at pkg/queryfrontend/config.go:301
return err
}
}
if cfg.LabelsConfig.ResultsCacheConfig != nil {
if cfg.LabelsConfig.SplitQueriesByInterval <= 0 {
return errors.New("split queries interval should be greater than 0 when caching is enabled")
}
if err := cfg.LabelsConfig.ResultsCacheConfig.Validate(querier.Config{}); err != nil {
return errors.Wrap(err, "invalid ResultsCache config for labels tripperware")
}
}
if cfg.DefaultTimeRange == 0 {
return errors.New("labels.default-time-range cannot be set to 0")
}
if cfg.DownstreamURL == "" {
return errors.New("downstream URL should be configured")
}
return nil
}
func (cfg *Config) validateDynamicSplitParams() error {
if cfg.HorizontalShards <= 0 {
return errors.New("min horizontal shards should be greater than 0 when query split threshold is enabled")
}
if cfg.MaxQuerySplitInterval <= 0 {
return errors.New("max query split interval should be greater than 0 when query split threshold is enabled")
}
if cfg.MinQuerySplitInterval <= 0 {
return errors.New("min query split interval should be greater than 0 when query split threshold is enabled")
}
return nilView on GitHub (pinned to 35b8b99117)