{"record":{"id":"b4015e5190bf514f","repo":"dgraph-io/badger","slug":"value-log-file-already-marked-for-deletion-fid-d","errorCode":null,"errorMessage":"value log file already marked for deletion fid: %d","messagePattern":"value log file already marked for deletion fid: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"value.go","lineNumber":167,"sourceCode":"\t\t}\n\t\treturn nil, err\n\t}\n\tcrc := y.BytesToU32(crcBuf[:])\n\tif crc != tee.Sum32() {\n\t\treturn nil, errTruncate\n\t}\n\te.meta = h.meta\n\te.UserMeta = h.userMeta\n\te.ExpiresAt = h.expiresAt\n\treturn e, nil\n}\n\nfunc (vlog *valueLog) rewrite(f *logFile) error {\n\tvlog.filesLock.RLock()\n\tfor _, fid := range vlog.filesToBeDeleted {\n\t\tif fid == f.fid {\n\t\t\tvlog.filesLock.RUnlock()\n\t\t\treturn fmt.Errorf(\"value log file already marked for deletion fid: %d\", fid)\n\t\t}\n\t}\n\tmaxFid := vlog.maxFid\n\ty.AssertTruef(f.fid < maxFid, \"fid to move: %d. Current max fid: %d\", f.fid, maxFid)\n\tvlog.filesLock.RUnlock()\n\n\tvlog.opt.Infof(\"Rewriting fid: %d\", f.fid)\n\n\t// Announce that a GC rewrite is in flight and pin the discard threshold to the\n\t// DB's current max committed version. While active, last-level compaction will\n\t// not purge any version newer than this point (see levelsController.subcompact),\n\t// so a tombstone for a key we are about to write back survives to shadow it,\n\t// preventing the deleted key from being resurrected (#2286). GC is serialized by\n\t// garbageCh (one rewrite at a time), so this per-DB state is not subject to\n\t// concurrent rewrites; the clamp is released on every exit path.\n\t//\n\t// MaxVersion() (not orc.nextTs()) is used deliberately: in managed mode\n\t// nextTxnTs is frozen at open time and does not track committed versions, so it","sourceCodeStart":149,"sourceCodeEnd":185,"githubUrl":"https://github.com/dgraph-io/badger/blob/2a001d466f6b71a917319a1db41f99860e16e269/value.go#L149-L185","documentation":"Returned by valueLog.rewrite (the GC path that rewrites a value-log file) when the file selected for rewrite is already listed in vlog.filesToBeDeleted. A file in that list has already been logically discarded by a previous GC run, so rewriting it would resurrect dead data; the guard rejects the operation so doRunGC should skip this file and pick another. The fault input is the GC candidate file f, racing or re-enqueueing an already-retired log file.","triggerScenarios":"Thrown at value.go:167 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Treat as a skip condition in GC: catch this error in the doRunGC caller, log it at debug/info, and continue with the next candidate file","Avoid invoking RunValueLogGC concurrently from multiple goroutines against the same directory — serialize GC runs","Do not retry the same file immediately; on the next GC pass the file will have been physically deleted"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"2a001d466f6b71a917319a1db41f99860e16e269","analyzedAt":"2026-09-05T13:00:02.264Z","contentChangedAt":"2026-09-05T13:00:02.264Z","schemaVersion":2},"datasetVersion":"2026-09-12T17:17:11.597Z"}