thanos-io/thanos · error
failed to run post compaction callback for result block
Error message
failed to run post compaction callback for result block %s
What it means
Wraps compactionLifecycleCallback.PostCompactionCallback for an already-uploaded result block: the registered post-compaction hook (e.g. cache invalidation or downstream notification) failed after the block was committed to the bucket. The error is retryable — the callback may re-run for the same block.
Solutions
- Inspect the callback's underlying error
- Check bucket permissions for cleanup operations
- Allow the compactor to retry
Defensive patterns
Strategy: retry
When it happens
Trigger: Thrown at pkg/compact/compact.go:1363 when the library encounters an invalid state.
Common situations: See trigger scenarios.
AI-assisted analysis of thanos-io/thanos@35b8b99117 (2026-09-07).
Data as JSON: /api/errors/bb434479aaef4793.
Report an issue: GitHub.
Appendix: source
Thrown at pkg/compact/compact.go:1363
// unless vertical compaction is enabled.
if !cg.enableVerticalCompaction {
if err := cg.areBlocksOverlapping(newMeta, toCompact...); err != nil {
return false, nil, halt(errors.Wrapf(err, "resulted compacted block %s overlaps with something", bdir))
}
}
begin = time.Now()
err = tracing.DoInSpanWithErr(ctx, "compaction_block_upload", func(ctx context.Context) error {
return block.Upload(ctx, cg.logger, cg.bkt, bdir, cg.hashFunc, objstore.WithUploadConcurrency(cg.blockFilesConcurrency))
})
if err != nil {
return false, nil, retry(errors.Wrapf(err, "upload of %s failed", compID))
}
level.Info(cg.logger).Log("msg", "uploaded block", "result_block", compID, "duration", time.Since(begin), "duration_ms", time.Since(begin).Milliseconds())
level.Info(cg.logger).Log("msg", "running post compaction callback", "result_block", compID)
if err := compactionLifecycleCallback.PostCompactionCallback(ctx, cg.logger, cg, compID); err != nil {
return false, nil, retry(errors.Wrapf(err, "failed to run post compaction callback for result block %s", compID))
}
level.Info(cg.logger).Log("msg", "finished running post compaction callback", "result_block", compID)
}
// Mark for deletion the blocks we just compacted from the group and bucket so they do not get included
// into the next planning cycle.
// Eventually the block we just uploaded should get synced into the group again (including sync-delay).
for _, meta := range toCompact {
if err := tracing.DoInSpanWithErr(ctx, "compaction_block_delete", func(ctx context.Context) error {
return cg.deleteBlock(meta.ULID, filepath.Join(dir, meta.ULID.String()), blockDeletableChecker)
}, opentracing.Tags{"block.id": meta.ULID}); err != nil {
return false, nil, retry(errors.Wrapf(err, "mark old block for deletion from bucket"))
}
cg.groupGarbageCollectedBlocks.Inc()
}
level.Info(cg.logger).Log("msg", "finished compacting blocks", "duration", time.Since(groupCompactionBegin),
"duration_ms", time.Since(groupCompactionBegin).Milliseconds(), "result_blocks", compIDStrs, "source_blocks", sourceBlockStr)View on GitHub (pinned to 35b8b99117)