thanos-io/thanos · error

min horizontal shards should be greater than 0 when query…

Error message

min horizontal shards should be greater than 0 when query split threshold is enabled

What it means

validateDynamicSplitParams enforces that all dynamic query-splitting settings are positive when the split-by-query-threshold feature is in use. HorizontalShards is the minimum number of horizontal shards, so a value <= 0 makes the shard math undefined; startup fails with this error.

Solutions

  1. Set query_frontend.horizontal_shards to a positive integer (e.g. 3)
  2. If dynamic splitting is not desired, disable query_split_threshold so validateDynamicSplitParams semantics don't apply
  3. Validate config before deploy with cortex's config validation

Example fix

// before
query_frontend:
  query_split_threshold: 100000
  # horizontal_shards not set
// after
query_frontend:
  query_split_threshold: 100000
  horizontal_shards: 3
Defensive patterns

Strategy: validation

Validate before calling

if cfg.HorizontalShards <= 0 {
    return errors.New("horizontal_shards must be > 0 when query_split_threshold is enabled")
}

Type guard

func dynamicSplitReady(cfg Config) bool {
    return cfg.HorizontalShards > 0 && cfg.MaxQuerySplitInterval > 0 && cfg.MinQuerySplitInterval > 0
}

Try / catch

if err := cfg.Validate(); err != nil {
    if strings.Contains(err.Error(), "horizontal shards") {
        log.Fatalf("set horizontal_shards > 0: %v", err)
    }
}

Prevention

When it happens

Trigger: Validate -> validateDynamicSplitParams is called with cfg.HorizontalShards <= 0, i.e. query_split_threshold is enabled (or dynamic splitting active) but horizontal_shards was left at its zero value or set to a negative number.

Common situations: Operators enabling query_split_threshold but omitting horizontal_shards; configs where horizontal_shards was intended to mean 'unlimited' and set to 0; upgrade paths where new dynamic-split fields default to zero.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


AI-assisted analysis of thanos-io/thanos@35b8b99117 (2026-09-07). Data as JSON: /api/errors/a8db06c0380bfe36. Report an issue: GitHub.

Appendix: source

Thrown at pkg/queryfrontend/config.go:309

		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 nil
}

func (cfg *Config) isStaticSplitSet() bool {
	return cfg.QueryRangeConfig.SplitQueriesByInterval != 0
}

func (cfg *Config) isDynamicSplitSet() bool {
	return cfg.MinQuerySplitInterval > 0 ||

View on GitHub (pinned to 35b8b99117)