{"record":{"id":"9ff5f0d1dc91929a","repo":"dgraph-io/badger","slug":"invalid-read-len-d-read-at-d-d","errorCode":null,"errorMessage":"Invalid read: Len: %d read at:[%d:%d]","messagePattern":"Invalid read: Len: (.+?) read at:\\[(.+?):(.+?)\\]","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"value.go","lineNumber":998,"sourceCode":"\t\t// Fetch checksum from the end of the buffer.\n\t\tchecksum := buf[len(buf)-crc32.Size:]\n\t\tif hash.Sum32() != y.BytesToU32(checksum) {\n\t\t\trunCallback(cb)\n\t\t\treturn nil, nil, y.Wrapf(y.ErrChecksumMismatch, \"value corrupted for vp: %+v\", vp)\n\t\t}\n\t}\n\tvar h header\n\theaderLen := h.Decode(buf)\n\tkv := buf[headerLen:]\n\tif lf.encryptionEnabled() {\n\t\tkv, err = lf.decryptKV(kv, vp.Offset)\n\t\tif err != nil {\n\t\t\treturn nil, cb, err\n\t\t}\n\t}\n\tif uint32(len(kv)) < h.klen+h.vlen {\n\t\tvlog.db.opt.Errorf(\"Invalid read: vp: %+v\", vp)\n\t\treturn nil, nil, fmt.Errorf(\"Invalid read: Len: %d read at:[%d:%d]\",\n\t\t\tlen(kv), h.klen, h.klen+h.vlen)\n\t}\n\treturn kv[h.klen : h.klen+h.vlen], cb, nil\n}\n\n// getUnlockCallback will returns a function which unlock the logfile if the logfile is mmaped.\n// otherwise, it unlock the logfile and return nil.\nfunc (vlog *valueLog) getUnlockCallback(lf *logFile) func() {\n\tif lf == nil {\n\t\treturn nil\n\t}\n\treturn lf.lock.RUnlock\n}\n\n// readValueBytes return vlog entry slice and read locked log file. Caller should take care of\n// logFile unlocking.\nfunc (vlog *valueLog) readValueBytes(vp valuePointer) ([]byte, *logFile, error) {\n\tlf, err := vlog.getFileRLocked(vp)","sourceCodeStart":980,"sourceCodeEnd":1016,"githubUrl":"https://github.com/dgraph-io/badger/blob/2a001d466f6b71a917319a1db41f99860e16e269/value.go#L980-L1016","documentation":"Read parses a key-value entry from the value log at the given value pointer: it reads the entry header (h.klen + h.vlen) and slices the value out of the fetched byte slice kv. If kv is shorter than the declared key+value length, the entry extends beyond the readable data — a truncated or corrupt vlog entry — so badger logs details and returns this error instead of garbage.","triggerScenarios":"Reading a key whose vlog entry is cut short: vlog truncated by a crash before fsync, disk corruption, an entry overwritten via a bad valuePointer, or a vlog written by an incompatible badger version with a different header layout.","commonSituations":"Power loss with SyncWrites=false leaving a partial entry; backing up a vlog mid-write; bit rot or failing disk; opening vlogs from a different badger version.","solutions":["Restore the vlog files from a known-good backup; the truncated entry is unrecoverable from the log itself.","Re-put affected keys from the application's source of truth so fresh entries are written at valid offsets.","Rely on badger's vlog replay/recovery (it truncates to the last valid entry on open); ensure a version that does this and reopen cleanly.","If caused by version mismatch, migrate with Stream/Backup into a fresh DB instead of opening old files in-place.","Check disk health (SMART/fsck) and stop copying live DB directories; use DB.Backup or stopped-DB snapshots."],"exampleFix":"// before: reading after a crash with a truncated vlog\nval, err := txn.Get(key) // Invalid read: Len: 100 read at:[10:150]\n// after: guard the read and rewrite the entry when corrupt\nval, err := txn.Get(key)\nif err != nil && strings.Contains(err.Error(), \"Invalid read\") {\n    regenerateAndPut(key) // rebuild value from app source of truth\n}","handlingStrategy":"fallback","validationCode":"// Go: verify vlog files are non-truncated before open (size sanity)\nfunc checkVlogIntegrity(dir string) error {\n    return filepath.Walk(dir, func(p string, fi os.FileInfo, err error) error {\n        if err == nil && strings.HasSuffix(p, \".vlog\") && fi.Size() < 20 {\n            return fmt.Errorf(\"vlog %s suspiciously small/truncated\", p)\n        }\n        return nil\n    })\n}","typeGuard":"func isInvalidReadErr(err error) bool {\n    return err != nil && strings.Contains(err.Error(), \"Invalid read: Len:\")\n}","tryCatchPattern":"item, err := txn.Get(key)\nif err != nil && isInvalidReadErr(err) {\n    // corrupt/truncated vlog entry: fall back to app source of truth\n    log.Printf(\"corrupt vlog entry for %s: %v\", key, err)\n    return regenerateValue(key)\n}","preventionTips":["Enable opt.SyncWrites for durability against partial entries on crash.","Never back up a live badger directory mid-write; stop the DB or use DB.Backup.","Keep badger versions consistent between write and read of a data directory.","Monitor disk health (SMART) and fsck after suspected corruption."],"tags":["badger","value-log","corruption","truncated-entry"],"backgroundTag":"vlog-entry-corrupt","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"}