{"record":{"id":"45da5834beb378d9","repo":"thanos-io/thanos","slug":"requested-to-mark-for-no-compaction-but-file-alre","errorCode":null,"errorMessage":"requested to mark for no compaction, but file already exists; this should not happen; investigate","messagePattern":"requested to mark for no compaction, but file already exists; this should not happen; investigate","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"pkg/block/block.go","lineNumber":389,"sourceCode":"\t\treturn nil, errors.Wrapf(err, \"stat %v\", filepath.Join(blockDir, MetaFilename))\n\t}\n\tres = append(res, metadata.File{RelPath: metaFile.Name()})\n\n\tsort.Slice(res, func(i, j int) bool {\n\t\treturn strings.Compare(res[i].RelPath, res[j].RelPath) < 0\n\t})\n\treturn res, err\n}\n\n// MarkForNoCompact creates a file which marks block to be not compacted.\nfunc MarkForNoCompact(ctx context.Context, logger log.Logger, bkt objstore.Bucket, id ulid.ULID, reason metadata.NoCompactReason, details string, markedForNoCompact prometheus.Counter) error {\n\tm := path.Join(id.String(), metadata.NoCompactMarkFilename)\n\tnoCompactMarkExists, err := bkt.Exists(ctx, m)\n\tif err != nil {\n\t\treturn errors.Wrapf(err, \"check exists %s in bucket\", m)\n\t}\n\tif noCompactMarkExists {\n\t\tlevel.Warn(logger).Log(\"msg\", \"requested to mark for no compaction, but file already exists; this should not happen; investigate\", \"err\", errors.Errorf(\"file %s already exists in bucket\", m))\n\t\treturn nil\n\t}\n\n\tnoCompactMark, err := json.Marshal(metadata.NoCompactMark{\n\t\tID:      id,\n\t\tVersion: metadata.NoCompactMarkVersion1,\n\n\t\tNoCompactTime: time.Now().Unix(),\n\t\tReason:        reason,\n\t\tDetails:       details,\n\t})\n\tif err != nil {\n\t\treturn errors.Wrap(err, \"json encode no compact mark\")\n\t}\n\n\tif err := bkt.Upload(ctx, m, bytes.NewBuffer(noCompactMark)); err != nil {\n\t\treturn errors.Wrapf(err, \"upload file %s to bucket\", m)\n\t}","sourceCodeStart":371,"sourceCodeEnd":407,"githubUrl":"https://github.com/thanos-io/thanos/blob/35b8b991177def87ed52dcf10f9b6d87f07282c8/pkg/block/block.go#L371-L407","documentation":"MarkForNoCompact found that the no-compact-mark.json file already exists in the bucket when it was asked to create it. This is not a wrapped error but a deliberate warning log; MarkForNoCompact returns nil (no error) after logging. It signals an unexpected duplicate mark — someone/something already marked the block, so the operation is idempotently skipped.","triggerScenarios":"bkt.Exists returns true for <id>/no-compact-mark.json: MarkForNoCompact (or a similar path) was invoked twice for the same block, e.g., duplicate compaction runs, retried operations, or two compactors working concurrently without leader election.","commonSituations":"Two compactor instances running concurrently (misconfigured HA); operation retried after a partial failure; block already marked by an earlier run with a different reason; manual mark created by an operator.","solutions":["Confirm only one compactor instance is running (leader election enabled, no duplicates).","Treat as benign if a duplicate mark is expected — the function returns nil and compaction is still skipped.","Inspect the existing no-compact-mark.json contents to see who marked it and with which reason/details.","If the mark is wrong (block should be compacted), delete the mark file from the bucket and rerun."],"exampleFix":"// before\nif noCompactMarkExists {\n\tlevel.Warn(logger).Log(\"msg\", \"requested to mark for no compaction, but file already exists; this should not happen; investigate\", \"err\", errors.Errorf(\"file %s already exists in bucket\", m))\n\treturn nil\n}\n// after\nif noCompactMarkExists {\n\tlevel.Warn(logger).Log(\"msg\", \"no-compact mark already exists; skipping\", \"file\", m)\n\treturn nil // idempotent: block already marked\n}","handlingStrategy":"try-catch","validationCode":"markPath := path.Join(id.String(), \"no-compact-mark.json\")\nexists, err := bkt.Exists(ctx, markPath)\nif err == nil && exists {\n\t// decide early: skip or fetch existing mark to compare reason\n\trc, _ := bkt.Get(ctx, markPath)\n\tb, _ := io.ReadAll(rc)\n\tlog.Printf(\"block %s already no-compact marked: %s\", id, b)\n}","typeGuard":null,"tryCatchPattern":"if err := block.MarkForNoCompact(...); err != nil {\n\treturn err\n}\n// on the warning log (returns nil), treat as idempotent success:\n// check logs for \"file already exists in bucket\" and proceed\n","preventionTips":["Ensure single compactor leadership (enable leader election; don't run duplicates).","Make mark operations idempotent — the function already returns nil on existing marks.","Before marking, read the existing mark to compare reasons instead of re-marking.","Use partitioned/sharded compaction so two instances never process the same block."],"tags":["object-storage","idempotency","thanos"],"backgroundTag":"file-already-exists","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"}