{"record":{"id":"e04a4c2df0817c3f","repo":"dgraph-io/badger","slug":"unable-to-find-fid-d","errorCode":null,"errorMessage":"Unable to find fid: %d","messagePattern":"Unable to find fid: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"value.go","lineNumber":364,"sourceCode":"\t\t\t\t// Decrease the batch size to half.\n\t\t\t\tbatchSize = batchSize / 2\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\treturn err\n\t\t}\n\t\ti += batchSize\n\t}\n\tvlog.opt.Infof(\"Processed %d entries in %d loops\", len(wb), loops)\n\tvlog.opt.Infof(\"Total entries: %d. Moved: %d\", count, moved)\n\tvlog.opt.Infof(\"Removing fid: %d\", f.fid)\n\tvar deleteFileNow bool\n\t// Entries written to LSM. Remove the older file now.\n\t{\n\t\tvlog.filesLock.Lock()\n\t\t// Just a sanity-check.\n\t\tif _, ok := vlog.filesMap[f.fid]; !ok {\n\t\t\tvlog.filesLock.Unlock()\n\t\t\treturn fmt.Errorf(\"Unable to find fid: %d\", f.fid)\n\t\t}\n\t\tif vlog.iteratorCount() == 0 {\n\t\t\tdelete(vlog.filesMap, f.fid)\n\t\t\tdeleteFileNow = true\n\t\t} else {\n\t\t\tvlog.filesToBeDeleted = append(vlog.filesToBeDeleted, f.fid)\n\t\t}\n\t\tvlog.filesLock.Unlock()\n\t}\n\n\tif deleteFileNow {\n\t\tif err := vlog.deleteLogFile(f); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\treturn nil\n}\n","sourceCodeStart":346,"sourceCodeEnd":382,"githubUrl":"https://github.com/dgraph-io/badger/blob/2a001d466f6b71a917319a1db41f99860e16e269/value.go#L346-L382","documentation":"Thrown by valueLog.rewrite (value.go:364) during GC (doRunGC): after moving surviving entries to new log files, the code removes the old file from filesMap but a sanity check finds f.fid is no longer (or never was) present, so the GC run returns this error instead of proceeding.","triggerScenarios":"Running vlog.RunGC/DB.RunValueLogGC when the target log file was already deleted or replaced by a concurrent GC/iterator cleanup, or after external manipulation/removal of .vlog files while the DB is open.","commonSituations":"Two GC loops racing on the same value-log file, calling RunValueLogGC on an already-collected file id, operator deleting a .vlog file mid-run, crash-recovery removing files between selection and rewrite.","solutions":["Treat it as a benign end-state in GC loops: catch it and skip that fid, re-listing vlog files for the next GC candidate.","Ensure only one goroutine runs value-log GC at a time (serialize with a mutex or worker).","Re-run GC later on a still-present file id obtained from vlog.filesMap/lf, rather than a stale cached fid.","Do not delete .vlog files externally while the DB is open; let badger's GC delete them.","If persistent, restart the DB to rebuild filesMap and retry GC."],"exampleFix":"// before\nerr := db.RunValueLogGC(0.5)\nif err != nil { log.Fatal(err) }\n// after\nerr := db.RunValueLogGC(0.5)\nif err != nil && !strings.Contains(err.Error(), \"Unable to find fid\") && !errors.Is(err, badger.ErrRejected) {\n    log.Fatal(err)\n} // otherwise: file already rewritten/removed; retry GC on next cycle","handlingStrategy":"try-catch","validationCode":"// before GC, check the file still exists in the live set\ninfo, err := db.Opts() // or track fids via value log registry\n// simplest guard: only run GC sequentially from a single worker goroutine\nvar gcMu sync.Mutex\nfunc safeRunGC(db *badger.DB, ratio float64) error {\n    gcMu.Lock(); defer gcMu.Unlock()\n    return db.RunValueLogGC(ratio)\n}","typeGuard":"func isFidNotFoundErr(err error) bool {\n    return err != nil && strings.Contains(err.Error(), \"Unable to find fid\")\n}","tryCatchPattern":"err := db.RunValueLogGC(0.5)\nswitch {\ncase err == nil:\n    // GC done\ncase errors.Is(err, badger.ErrNoRewrite), isFidNotFoundErr(err):\n    // file already rewritten/removed: benign, skip and pick another fid later\ndefault:\n    return err\n}","preventionTips":["Run value-log GC from a single dedicated goroutine; never concurrently.","Persist/retry using current file ids, not stale ids cached across restarts.","Never delete *.vlog files manually while the DB is open.","Handle ErrNoRewrite-like outcomes as normal GC flow, not fatal errors."],"tags":["go","badger","value-log","garbage-collection","concurrency"],"backgroundTag":"gc-file-not-found","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"}