thanos-io/thanos · error
Given error is not an issue347 error
Error message
Given error is not an issue347 error: %v
What it means
RepairIssue347 only repairs errors whose cause is an Issue347Error (the Prometheus tsdb issue 347 index-corruption error). It type-asserts errors.Cause(issue347Err) to Issue347Error and returns this error when the assertion fails, meaning the caller passed an overlap or other error that is not the specific issue-347 corruption and thus cannot be auto-repaired by this function.
Solutions
- Inspect the original error: if it's generic overlap, find the real root cause (duplicate uploads, second compactor) instead of calling RepairIssue347
- Only invoke RepairIssue347 when errors.Is/Cause chain contains an Issue347Error (blocks affected by prometheus/tsdb#347)
- For non-347 overlaps, delete or no-compact-mark the offending blocks manually
- Unwrap correctly: pass the error with its cause chain intact (don't fmt.Errorf without %w)
Example fix
// before
var ie Issue347Error
if !errors.As(err, &ie) { return }
RepairIssue347(ctx, logger, bkt, ctr, err) // panics/error if not issue347
// after
var ie Issue347Error
if errors.As(err, &ie) {
RepairIssue347(ctx, logger, bkt, ctr, err)
} Defensive patterns
Strategy: type-guard
Validate before calling
var ie compact.Issue347Error
if !errors.As(err, &ie) {
// do NOT call RepairIssue347; handle as a generic overlap
return handleGenericOverlap(err)
} Type guard
func isIssue347Err(err error) bool {
var ie compact.Issue347Error
return errors.As(err, &ie)
} Try / catch
// Go
var ie compact.Issue347Error
if errors.As(err, &ie) {
if rerr := compact.RepairIssue347(ctx, logger, bkt, marks, err); rerr != nil {
logger.Error("issue347 repair failed", "err", rerr)
}
} else {
logger.Warn("not repairable as issue347", "err", err)
} Prevention
- Always check errors.As(..., *Issue347Error) before calling RepairIssue347
- Preserve the error cause chain when wrapping (use %w)
- Classify overlap errors before choosing a repair path
- Log the original error to distinguish 347 corruption from dual-compactor overlaps
When it happens
Trigger: Calling RepairIssue347 with an error whose cause is not an Issue347Error — e.g. a plain 'overlaps found while gathering blocks' error from a different root cause, or a wrapped error from another failure mode.
Common situations: Automation/scripts that blanket-call RepairIssue347 for every overlap error; a compactor configured with repair enabled encountering overlaps not caused by issue 347 (dual compactor, manual uploads); calling the function directly with a wrapped error that lost the Issue347Error cause chain.
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
- Query not explainable
- found chunks non-completely outside the block time range…
- no ignore chunk function specified
- add symbol
- next symbol
AI-assisted analysis of thanos-io/thanos@35b8b99117 (2026-09-07).
Data as JSON: /api/errors/b699c5469ff9c012.
Report an issue: GitHub.
Appendix: source
Thrown at pkg/compact/compact.go:1113
if include != nil {
metas = append(metas, include.BlockMeta)
}
sort.Slice(metas, func(i, j int) bool {
return metas[i].MinTime < metas[j].MinTime
})
if overlaps := tsdb.OverlappingBlocks(metas); len(overlaps) > 0 {
return errors.Errorf("overlaps found while gathering blocks. %s", overlaps)
}
return nil
}
// RepairIssue347 repairs the https://github.com/prometheus/tsdb/issues/347 issue when having issue347Error.
func RepairIssue347(ctx context.Context, logger log.Logger, bkt objstore.Bucket, blocksMarkedForDeletion prometheus.Counter, issue347Err error) error {
ie, ok := errors.Cause(issue347Err).(Issue347Error)
if !ok {
return errors.Errorf("Given error is not an issue347 error: %v", issue347Err)
}
level.Info(logger).Log("msg", "Repairing block broken by https://github.com/prometheus/tsdb/issues/347", "id", ie.id, "err", issue347Err)
tmpdir, err := os.MkdirTemp("", fmt.Sprintf("repair-issue-347-id-%s-", ie.id))
if err != nil {
return err
}
defer func() {
if err := os.RemoveAll(tmpdir); err != nil {
level.Warn(logger).Log("msg", "failed to remote tmpdir", "err", err, "tmpdir", tmpdir)
}
}()
bdir := filepath.Join(tmpdir, ie.id.String())
if err := block.Download(ctx, logger, bkt, ie.id, bdir); err != nil {
return retry(errors.Wrapf(err, "download block %s", ie.id))View on GitHub (pinned to 35b8b99117)