hyperledger/fabric · error
error reading [%d] bytes from file number [%d]
Error message
error reading [%d] bytes from file number [%d]
What it means
Wraps the io.ReadAtLeast error when reading the block body of `length` bytes after the size prefix was discarded. io.ReadAtLeast returns io.ErrUnexpectedEOF if EOF is hit before `length` bytes are read, or the underlying read error otherwise. The error is logged with Errorf before wrapping, and usually means the file holds less data than the block's declared size.
Source
Thrown at common/ledger/blkstorage/block_stream.go:130
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,
blockStartOffset: s.currentOffset,
blockBytesOffset: s.currentOffset + int64(n),
}
s.currentOffset += int64(n) + int64(length)
logger.Debugf("Returning blockbytes - length=[%d], placementInfo={%s}", len(blockBytes), blockPlacementInfo)
return blockBytes, blockPlacementInfo, nil
}
func (s *blockfileStream) close() error {
return errors.WithStack(s.file.Close())
}
// /////////////////////////////////
// blockStream functions
// //////////////////////////////////View on GitHub (pinned to 2736b63f8f)
Solutions
- Handle it like a torn write: recover by truncating the file after the last complete block (this is how Fabric recovery treats it)
- Check disk space and filesystem fsync behavior on the ledger volume
- Never copy ledger files from a live peer; take a stopped-peer snapshot or use snapshot service
- If it recurs on a healthy file, verify storage integrity and restore from backup/re-sync
Example fix
// before
blockBytes, err := readBlock(stream)
if err != nil { return err }
// after
if _, err := readBlock(stream); err != nil {
if errors.Is(errors.Cause(err), io.ErrUnexpectedEOF) {
return recoverTornTail(file) // truncate after last complete block
}
return err
} Defensive patterns
Strategy: try-catch
Validate before calling
info, err := os.Stat(blockfilePath)
if err != nil || info.Size() < expectedMinSize {
return fmt.Errorf("file shorter than expected; torn write likely")
} Type guard
func isShortRead(err error) bool {
c := errors.Cause(err)
return errors.Is(c, io.ErrUnexpectedEOF) || errors.Is(c, io.EOF)
} Try / catch
blk, err := stream.nextBlockBytes()
if err != nil {
if isShortRead(err) {
logger.Warningf("torn block append detected: %v", err)
return truncateAfterLastCompleteBlock(blockfilePath)
}
return err
} Prevention
- Ensure adequate disk space so appends never fail mid-block
- Shut down the peer cleanly before snapshots or copies
- Use storage with reliable fsync/barrier support
- Reconcile ledger files with the checkpoint via peer rollback after crashes
When it happens
Trigger: nextBlockBytesAndPlacementInfo: the varint prefix declared `length` bytes but io.ReadAtLeast(s.reader, blockBytes, length) hits EOF early — a torn append where the size prefix was written but the body was not fully flushed.
Common situations: Peer crash or power loss between writing the length prefix and the block body; disk-full cutting an append short; reading a blockfile copied mid-write from a running peer.
Related errors
- unexpected end of blockfile
- error peeking [%d] bytes from block file
- error discarding [%d] bytes
- failed to create target folder for connection.json: %s
- error reading input
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/914e5f440099136a.
Report an issue: GitHub.