{"record":{"id":"b699c5469ff9c012","repo":"thanos-io/thanos","slug":"given-error-is-not-an-issue347-error-v","errorCode":null,"errorMessage":"Given error is not an issue347 error: %v","messagePattern":"Given error is not an issue347 error: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/compact/compact.go","lineNumber":1113,"sourceCode":"\n\tif include != nil {\n\t\tmetas = append(metas, include.BlockMeta)\n\t}\n\n\tsort.Slice(metas, func(i, j int) bool {\n\t\treturn metas[i].MinTime < metas[j].MinTime\n\t})\n\tif overlaps := tsdb.OverlappingBlocks(metas); len(overlaps) > 0 {\n\t\treturn errors.Errorf(\"overlaps found while gathering blocks. %s\", overlaps)\n\t}\n\treturn nil\n}\n\n// RepairIssue347 repairs the https://github.com/prometheus/tsdb/issues/347 issue when having issue347Error.\nfunc RepairIssue347(ctx context.Context, logger log.Logger, bkt objstore.Bucket, blocksMarkedForDeletion prometheus.Counter, issue347Err error) error {\n\tie, ok := errors.Cause(issue347Err).(Issue347Error)\n\tif !ok {\n\t\treturn errors.Errorf(\"Given error is not an issue347 error: %v\", issue347Err)\n\t}\n\n\tlevel.Info(logger).Log(\"msg\", \"Repairing block broken by https://github.com/prometheus/tsdb/issues/347\", \"id\", ie.id, \"err\", issue347Err)\n\n\ttmpdir, err := os.MkdirTemp(\"\", fmt.Sprintf(\"repair-issue-347-id-%s-\", ie.id))\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tdefer func() {\n\t\tif err := os.RemoveAll(tmpdir); err != nil {\n\t\t\tlevel.Warn(logger).Log(\"msg\", \"failed to remote tmpdir\", \"err\", err, \"tmpdir\", tmpdir)\n\t\t}\n\t}()\n\n\tbdir := filepath.Join(tmpdir, ie.id.String())\n\tif err := block.Download(ctx, logger, bkt, ie.id, bdir); err != nil {\n\t\treturn retry(errors.Wrapf(err, \"download block %s\", ie.id))","sourceCodeStart":1095,"sourceCodeEnd":1131,"githubUrl":"https://github.com/thanos-io/thanos/blob/35b8b991177def87ed52dcf10f9b6d87f07282c8/pkg/compact/compact.go#L1095-L1131","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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)"],"exampleFix":"// before\nvar ie Issue347Error\nif !errors.As(err, &ie) { return }\nRepairIssue347(ctx, logger, bkt, ctr, err) // panics/error if not issue347\n// after\nvar ie Issue347Error\nif errors.As(err, &ie) {\n    RepairIssue347(ctx, logger, bkt, ctr, err)\n}","handlingStrategy":"type-guard","validationCode":"var ie compact.Issue347Error\nif !errors.As(err, &ie) {\n    // do NOT call RepairIssue347; handle as a generic overlap\n    return handleGenericOverlap(err)\n}","typeGuard":"func isIssue347Err(err error) bool {\n    var ie compact.Issue347Error\n    return errors.As(err, &ie)\n}","tryCatchPattern":"// Go\nvar ie compact.Issue347Error\nif errors.As(err, &ie) {\n    if rerr := compact.RepairIssue347(ctx, logger, bkt, marks, err); rerr != nil {\n        logger.Error(\"issue347 repair failed\", \"err\", rerr)\n    }\n} else {\n    logger.Warn(\"not repairable as issue347\", \"err\", err)\n}","preventionTips":["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"],"tags":["repair","type-assertion","issue347"],"backgroundTag":"invalid-argument-value","analyzedSha":"35b8b991177def87ed52dcf10f9b6d87f07282c8","analyzedAt":"2026-09-07T01:49:59.689Z","contentChangedAt":"2026-09-07T01:49:59.689Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}