hyperledger/fabric · critical
Error in decoding varint bytes [%#v]
Error message
Error in decoding varint bytes [%#v]
What it means
A panic raised when protowire.ConsumeVarint returns n <= 0 on the peeked length-prefix bytes while moreContentAvailable is still true. This means the bytes at the current offset are not a valid varint at all — corruption, not a torn tail (a torn tail with no more content returns ErrUnexpectedEndOfBlockfile instead). The code cannot make any progress, so it panics.
Source
Thrown at common/ledger/blkstorage/block_stream.go:115
// Peek 8 or smaller number of bytes (if remaining bytes are less than 8)
// Assumption is that a block size would be small enough to be represented in 8 bytes varint
peekBytes := 8
if remainingBytes < int64(peekBytes) {
peekBytes = int(remainingBytes)
moreContentAvailable = false
}
logger.Debugf("Remaining bytes=[%d], Going to peek [%d] bytes", remainingBytes, peekBytes)
if lenBytes, err = s.reader.Peek(peekBytes); err != nil {
return nil, nil, errors.Wrapf(err, "error peeking [%d] bytes from block file", peekBytes)
}
length, n := protowire.ConsumeVarint(lenBytes)
if n <= 0 {
// proto.DecodeVarint did not consume any byte at all which means that the bytes
// representing the size of the block are partial bytes
if !moreContentAvailable {
return nil, nil, ErrUnexpectedEndOfBlockfile
}
panic(errors.Errorf("Error in decoding varint bytes [%#v]", lenBytes))
}
bytesExpected := int64(n) + int64(length)
if bytesExpected > remainingBytes {
logger.Debugf("At least [%d] bytes expected. Remaining bytes = [%d]. Returning with error [%s]",
bytesExpected, remainingBytes, ErrUnexpectedEndOfBlockfile)
return nil, nil, ErrUnexpectedEndOfBlockfile
}
// skip the bytes representing the block size
if _, err = s.reader.Discard(n); err != nil {
return nil, nil, errors.Wrapf(err, "error discarding [%d] bytes", n)
}
blockBytes := make([]byte, length)
if _, err = io.ReadAtLeast(s.reader, blockBytes, int(length)); err != nil {
logger.Errorf("Error reading [%d] bytes from file number [%d], error: %s", length, s.fileNum, err)
return nil, nil, errors.Wrapf(err, "error reading [%d] bytes from file number [%d]", length, s.fileNum)
}
blockPlacementInfo := &blockPlacementInfo{
fileNum: s.fileNum,View on GitHub (pinned to 2736b63f8f)
Solutions
- Treat as file corruption: run ledger integrity checks and restore the blockfile from backup or re-sync from other peers/orderers
- Verify no external process wrote to the ledger directory
- Check the offset source — a corrupt checkpoint can point mid-block; rebuild the checkpoint/rollback
- Check storage health (SMART, dmesg) for bit rot
Defensive patterns
Strategy: validation
Validate before calling
func looksLikeVarintPrefix(b []byte) bool {
_, n := protowire.ConsumeVarint(b)
return n > 0
} Try / catch
defer func() {
if r := recover(); r != nil {
logger.Errorf("blockfile corruption: %v", r)
triggerLedgerRebuild()
}
}() Prevention
- Use ECC/scrubbed storage; monitor SMART for bit rot
- Restrict ledger directory write access to the peer user only
- Verify integrity after any manual restore of ledger files
- Keep backups/snapshots of ledger data
When it happens
Trigger: nextBlockBytesAndPlacementInfo peeks bytes, ConsumeVarint fails (n<=0), AND moreContentAvailable==true — i.e. remaining bytes >= peekBytes but they do not decode as a varint length prefix.
Common situations: Bit rot / disk corruption of the blockfile; writes to the file from an unexpected process; reading a non-blockfile or a file with a wrong offset (corrupt checkpoint); manually edited or patched ledger files.
Related errors
- Could not seek block file [%s] to startOffset [%d]. New posi
- Could not retrieve header of the last block form file: %s
- Cannot decode the block %d
- enrollment certificate is not a valid x509 certificate: %v
- panic(err)
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/79cd4d85dac14933.
Report an issue: GitHub.