dgraph-io/badger · error

Invalid value pointer offset: %d greater than current offset

Error message

Invalid value pointer offset: %d greater than current offset: %d

What it means

After locating the log file for a value pointer, getFileRLocked validates the offset: when reading from the currently writable log (vp.Fid == maxFid, non-readonly), the pointer's offset must be strictly less than the log's current write offset (vlog.woffset()). A value pointer at or past the write head points at data that was never durably written, indicating truncation or corruption.

Source

Thrown at value.go:953

// Gets the logFile and acquires and RLock() for the mmap. You must call RUnlock on the file
// (if non-nil)
func (vlog *valueLog) getFileRLocked(vp valuePointer) (*logFile, error) {
	vlog.filesLock.RLock()
	defer vlog.filesLock.RUnlock()
	ret, ok := vlog.filesMap[vp.Fid]
	if !ok {
		// log file has gone away, we can't do anything. Return.
		return nil, fmt.Errorf("file with ID: %d not found", vp.Fid)
	}

	// Check for valid offset if we are reading from writable log.
	maxFid := vlog.maxFid
	// In read-only mode we don't need to check for writable offset as we are not writing anything.
	// Moreover, this offset is not set in readonly mode.
	if !vlog.opt.ReadOnly && vp.Fid == maxFid {
		currentOffset := vlog.woffset()
		if vp.Offset >= currentOffset {
			return nil, fmt.Errorf(
				"Invalid value pointer offset: %d greater than current offset: %d",
				vp.Offset, currentOffset)
		}
	}

	ret.lock.RLock()
	return ret, nil
}

// Read reads the value log at a given location.
// TODO: Make this read private.
func (vlog *valueLog) Read(vp valuePointer, _ *y.Slice) ([]byte, func(), error) {
	buf, lf, err := vlog.readValueBytes(vp)
	// log file is locked so, decide whether to lock immediately or let the caller to
	// unlock it, after caller uses it.
	cb := vlog.getUnlockCallback(lf)
	if err != nil {
		return nil, cb, err

View on GitHub (pinned to 2a001d466f)

Solutions

  1. Restore LSM and vlog files as a consistent set from the same backup timestamp — never mix files from different points in time.
  2. Reduce crash-tail risk by enabling/tuning opt.SyncWrites; badger truncates the vlog tail on recovery, so SSTs must match the recovered state.
  3. If corruption is suspected, use badger recovery/verification tooling or rebuild via Stream/Backup into a fresh instance.
  4. Check hardware/disk issues (dmesg, fsck) if the write head regressed unexpectedly.
  5. Mitigate by iterating and rewriting affected key ranges so valuePointers are regenerated against current vlog state.

Example fix

// before: mixing a new SST backup with an older vlog file
$ cp new.sst /data/badger/ && cp old-000005.vlog /data/badger/
// read: Invalid value pointer offset: 9500 greater than current offset: 8192
// after: restore a consistent snapshot
$ rsync --archive snapshot@ts/ /data/badger/  # SSTs and vlogs from same checkpoint
// and reduce crash tail risk
opt.SyncWrites = true
Defensive patterns

Strategy: retry

Validate before calling

// Go: validate restore consistency — SST and vlog file timestamps should match
func restoreConsistent(snapshotDir, dataDir string) error {
    sstT := modTimeFirst(snapshotDir, "*.sst")
    vlogT := modTimeFirst(snapshotDir, "*.vlog")
    if !sstT.Equal(vlogT) && sstT.Sub(vlogT).Abs() > time.Minute {
        return errors.New("mixed vlog/SST generations — restore full snapshot")
    }
    return nil
}

Type guard

func isInvalidVpOffset(err error) bool {
    return err != nil && strings.Contains(err.Error(), "Invalid value pointer offset")
}

Try / catch

item, err := txn.Get(key)
if err != nil && isInvalidVpOffset(err) {
    // retry after rewriting the key to regenerate its value pointer
    if rwErr := regenerateAndPut(key); rwErr != nil {
        return rwErr
    }
    return txn.Get(key)
}

Prevention

When it happens

Trigger: Reading a value whose valuePointer offset >= the writable file's current offset — typically after a crash where the unsynced vlog tail was lost but an SST still holds a newer valuePointer, a corrupted valuePointer, or a manually truncated vlog file.

Common situations: Unsynced writes + hard crash/power loss; disk corruption or partial vlog truncation; restoring an older vlog file alongside newer SSTs (file-set version mismatch).

Related errors


AI-assisted analysis of dgraph-io/badger@2a001d466f (2026-09-05). Data as JSON: /api/errors/00468b7eebe611cb. Report an issue: GitHub.