thanos-io/thanos · critical
critical error detected
Error message
critical error detected
What it means
Thanos Compactor wraps errors it classifies as HaltError (non-retriable, potentially data-corrupting, e.g. duplicate compaction, corrupt block index) with the message 'critical error detected'. With --no-halt-on-error, instead of blocking forever (select{}), the compactor returns this wrapped error and the process exits. It signals a serious problem that requires manual investigation before rerunning.
Solutions
- Inspect the full wrapped error and the block IDs mentioned; run 'thanos tools bucket verify' on the affected block/group.
- Ensure only one compactor instance runs per bucket/resolution (check for duplicate deployments or lost lock).
- Remove or quarantine the corrupt/overlapping blocks using 'thanos tools bucket mark --marker=deletion-mark.json' after backup, then rerun the compactor.
- If you intentionally use --no-halt-on-error, add alerting on the thanos_compact_halted metric and on this error so the process failing is noticed and investigated.
Example fix
// before thanos compact --data-dir=/var/thanos/compact --objstore.bucket=thanos --no-halt-on-error // after thanos compact --data-dir=/var/thanos/compact --objstore.bucket=thanos # keep halt-on-error default (blocks for investigation) and alert on thanos_compact_halted==1
Defensive patterns
Strategy: validation
Validate before calling
// Before/while running compactor, ensure single ownership + verify bucket
# thanos tools bucket verify --objstore.bucket=thanos --objstore-backup.bucket=thanos-backup
if os.Getenv("THANOS_SINGLE_COMPACTOR") != "1" {
log.Fatal("refusing to start: only one compactor per bucket is allowed")
} Try / catch
// In custom runners, treat halt errors as fatal, never retry
if err := runCompaction(ctx); err != nil {
if compact.IsHaltError(err) {
alertHalting(err) // page on-call; do NOT restart-loop
os.Exit(1)
}
} Prevention
- Never run two compactors against the same bucket/resolution.
- Keep the default --halt-on-error and alert on thanos_compact_halted instead of auto-restarting.
- Run periodic 'thanos tools bucket verify' to catch corruption early.
- Monitor thanos_compact_group_compactions_failures_total for rising failure rates.
When it happens
Trigger: compact.Compact (or runCompaction) returns an err for which compact.IsHaltError(err) is true — most commonly ErrCompactionGroupMerge, ErrUnitAppend, ErrDuplicate_compaction or ErrBlocksOverlapping, or an index issue in a TSDB block during compaction. Only reached when conf.haltOnError is false (--no-halt-on-error flag was set).
Common situations: Operators running with --no-halt-on-error hit it when compactor races with another compactor instance (overlapping blocks), when a block's index.json is corrupted after an interrupted upload, or when metadata/labels are inconsistent in the bucket. Running two compactors for the same bucket without proper ownership is the classic cause.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- create bucket compactor
- compaction
- error executing compaction
- could not group metadata for compaction
- could not calculate compaction progress
AI-assisted analysis of thanos-io/thanos@35b8b99117 (2026-09-07).
Data as JSON: /api/errors/c0adb6e6c09ec77d.
Report an issue: GitHub.
Appendix: source
Thrown at cmd/thanos/compact.go:552
}
// --wait=true is specified.
return runutil.Repeat(conf.waitInterval, ctx.Done(), func() error {
err := compactMainFn()
if err == nil {
compactMetrics.iterations.Inc()
return nil
}
// The HaltError type signals that we hit a critical bug and should block
// for investigation. You should alert on this being halted.
if compact.IsHaltError(err) {
if conf.haltOnError {
level.Error(logger).Log("msg", "critical error detected; halting", "err", err)
compactMetrics.halted.Set(1)
select {}
} else {
return errors.Wrap(err, "critical error detected")
}
}
// The RetryError signals that we hit an retriable error (transient error, no connection).
// You should alert on this being triggered too frequently.
if compact.IsRetryError(err) {
level.Error(logger).Log("msg", "retriable error", "err", err)
compactMetrics.retried.Inc()
// TODO(bplotka): use actual "retry()" here instead of waiting 5 minutes?
return nil
}
return errors.Wrap(err, "error executing compaction")
})
}, func(error) {
cancel()
})
View on GitHub (pinned to 35b8b99117)