thanos-io/thanos · error

raw resolution must be higher than the minimum block size…

Error message

raw resolution must be higher than the minimum block size after which 5m resolution downsampling will occur (40 hours)

What it means

A configuration validation error in runCompact (cmd/thanos/compact.go:416). When downsampling is enabled and a raw retention is set, Thanos requires raw retention to be at least downsample.ResLevel1DownsampleRange (40 hours), otherwise 5m downsampling could never run before raw blocks are deleted, so the command refuses to start.

Solutions

  1. Increase --retention.raw to at least 40h (e.g. --retention.raw=40h or more)
  2. Pass --downsampling.disable if you intentionally keep raw data for less than 40h and do not want downsampled blocks
  3. Set --retention.raw=0s to disable raw retention entirely, which bypasses this check

Example fix

// before
thanos compact --downsampling.enabled --retention.raw=24h ...
// after
thanos compact --downsampling.enabled --retention.raw=40h ...
// or
thanos compact --downsampling.disable --retention.raw=24h ...
Defensive patterns

Strategy: validation

Validate before calling

rawRetention := time.Duration(conf.retentionRaw)
if rawRetention != 0 && !conf.disableDownsampling && rawRetention < 40*time.Hour {
	return errors.New("--retention.raw must be >= 40h when downsampling is enabled")
}

Prevention

When it happens

Trigger: --downsampling.enabled (default) plus --retention.raw set to a nonzero duration less than 40h (e.g. 24h).

Common situations: Operators lowering raw retention below 40h to save storage while leaving downsampling enabled; default downsampling enabled unnoticed.

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/3a4d15dcb0cd92e2. Report an issue: GitHub.

Appendix: source

Thrown at cmd/thanos/compact.go:416

		insBkt,
		conf.compactionConcurrency,
		conf.skipBlockWithOutOfOrderChunks,
		blocksCleaner,
	)
	if err != nil {
		return errors.Wrap(err, "create bucket compactor")
	}

	retentionByResolution := map[compact.ResolutionLevel]time.Duration{
		compact.ResolutionLevelRaw: time.Duration(conf.retentionRaw),
		compact.ResolutionLevel5m:  time.Duration(conf.retentionFiveMin),
		compact.ResolutionLevel1h:  time.Duration(conf.retentionOneHr),
	}

	if retentionByResolution[compact.ResolutionLevelRaw].Milliseconds() != 0 {
		// If downsampling is enabled, error if raw retention is not sufficient for downsampling to occur (upper bound 10 days for 1h resolution)
		if !conf.disableDownsampling && retentionByResolution[compact.ResolutionLevelRaw].Milliseconds() < downsample.ResLevel1DownsampleRange {
			return errors.New("raw resolution must be higher than the minimum block size after which 5m resolution downsampling will occur (40 hours)")
		}
		level.Info(logger).Log("msg", "retention policy of raw samples is enabled", "duration", retentionByResolution[compact.ResolutionLevelRaw])
	}
	if retentionByResolution[compact.ResolutionLevel5m].Milliseconds() != 0 {
		// If retention is lower than minimum downsample range, then no downsampling at this resolution will be persisted
		if !conf.disableDownsampling && retentionByResolution[compact.ResolutionLevel5m].Milliseconds() < downsample.ResLevel2DownsampleRange {
			return errors.New("5m resolution retention must be higher than the minimum block size after which 1h resolution downsampling will occur (10 days)")
		}
		level.Info(logger).Log("msg", "retention policy of 5 min aggregated samples is enabled", "duration", retentionByResolution[compact.ResolutionLevel5m])
	}
	if retentionByResolution[compact.ResolutionLevel1h].Milliseconds() != 0 {
		level.Info(logger).Log("msg", "retention policy of 1 hour aggregated samples is enabled", "duration", retentionByResolution[compact.ResolutionLevel1h])
	}

	var cleanMtx sync.Mutex
	// TODO(GiedriusS): we could also apply retention policies here but the logic would be a bit more complex.
	cleanPartialMarked := func() error {
		cleanMtx.Lock()

View on GitHub (pinned to 35b8b99117)