thanos-io/thanos · error

compaction-min must be less than or equal to compaction-max

Error message

compaction-min must be less than or equal to compaction-max

What it means

The replicate command derives compaction levels from --compaction-min and --compaction-max (when --compactions is not given). It explicitly rejects a configuration where min exceeds max with this error, because the generated level range would be empty/inverted.

Solutions

  1. Swap the values so compaction-min <= compaction-max (valid levels: 0, 1, 2).
  2. Alternatively pass an explicit --compactions list (e.g. --compactions=0,1) and the min/max check is skipped.
  3. Review automation scripts that compute min/max and enforce ordering before invoking the command.

Example fix

// before
thanos tools bucket replicate ... --compaction-min=2 --compaction-max=1
// after
thanos tools bucket replicate ... --compaction-min=1 --compaction-max=2
Defensive patterns

Strategy: validation

Validate before calling

if compactionMin > compactionMax {
    return errors.New("--compaction-min must be <= --compaction-max (valid levels: 0,1,2)")
}

Try / catch

if err := replicateCmd.Execute(); err != nil {
    if strings.Contains(err.Error(), "compaction-min must be less than or equal") {
        os.Exit(2) // fix flag ordering and retry
    }
}

Prevention

When it happens

Trigger: Running `thanos tools bucket replicate` with --compaction-min greater than --compaction-max (e.g. min=3 max=1) and no explicit --compactions list — cmd/thanos/tools_bucket.go:780.

Common situations: Users swapping the two flags on the command line or scripting where the values are computed in the wrong order; also confusion between compaction levels (0,1,2) and time ranges.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

Thrown at cmd/thanos/tools_bucket.go:780

	maxTime := model.TimeOrDuration(cmd.Flag("max-time", "End of time range limit to replicate. Thanos Replicate will replicate only metrics, which happened earlier than this value. Option can be a constant time in RFC3339 format or time duration relative to current time, such as -1d or 2h45m. Valid duration units are ms, s, m, h, d, w, y.").
		Default("9999-12-31T23:59:59Z"))
	ids := cmd.Flag("id", "Block to be replicated to the destination bucket. IDs will be used to match blocks and other matchers will be ignored. When specified, this command will be run only once after successful replication. Repeated field").Strings()
	ignoreMarkedForDeletion := cmd.Flag("ignore-marked-for-deletion", "Do not replicate blocks that have deletion mark.").Bool()

	cmd.Setup(func(g *run.Group, logger log.Logger, reg *prometheus.Registry, tracer opentracing.Tracer, _ <-chan struct{}, _ bool) error {
		matchers, err := replicate.ParseFlagMatchers(tbc.matcherStrs)
		if err != nil {
			return errors.Wrap(err, "parse block label matchers")
		}

		var resolutionLevels []compact.ResolutionLevel
		for _, lvl := range tbc.resolutions {
			resolutionLevels = append(resolutionLevels, compact.ResolutionLevel(lvl.Milliseconds()))
		}

		if len(tbc.compactions) == 0 {
			if tbc.compactMin > tbc.compactMax {
				return errors.New("compaction-min must be less than or equal to compaction-max")
			}
			tbc.compactions = []int{}
			for compactionLevel := tbc.compactMin; compactionLevel <= tbc.compactMax; compactionLevel++ {
				tbc.compactions = append(tbc.compactions, compactionLevel)
			}
		}

		blockIDs := make([]ulid.ULID, 0, len(*ids))
		for _, id := range *ids {
			bid, err := ulid.Parse(id)
			if err != nil {
				return errors.Wrap(err, "invalid ULID found in --id flag")
			}
			blockIDs = append(blockIDs, bid)
		}

		return replicate.RunReplicate(
			g,

View on GitHub (pinned to 35b8b99117)