{"record":{"id":"914e5f440099136a","repo":"hyperledger/fabric","slug":"error-reading-d-bytes-from-file-number-d","errorCode":null,"errorMessage":"error reading [%d] bytes from file number [%d]","messagePattern":"error reading \\[(.+?)\\] bytes from file number \\[(.+?)\\]","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"common/ledger/blkstorage/block_stream.go","lineNumber":130,"sourceCode":"\t\tif !moreContentAvailable {\n\t\t\treturn nil, nil, ErrUnexpectedEndOfBlockfile\n\t\t}\n\t\tpanic(errors.Errorf(\"Error in decoding varint bytes [%#v]\", lenBytes))\n\t}\n\tbytesExpected := int64(n) + int64(length)\n\tif bytesExpected > remainingBytes {\n\t\tlogger.Debugf(\"At least [%d] bytes expected. Remaining bytes = [%d]. Returning with error [%s]\",\n\t\t\tbytesExpected, remainingBytes, ErrUnexpectedEndOfBlockfile)\n\t\treturn nil, nil, ErrUnexpectedEndOfBlockfile\n\t}\n\t// skip the bytes representing the block size\n\tif _, err = s.reader.Discard(n); err != nil {\n\t\treturn nil, nil, errors.Wrapf(err, \"error discarding [%d] bytes\", n)\n\t}\n\tblockBytes := make([]byte, length)\n\tif _, err = io.ReadAtLeast(s.reader, blockBytes, int(length)); err != nil {\n\t\tlogger.Errorf(\"Error reading [%d] bytes from file number [%d], error: %s\", length, s.fileNum, err)\n\t\treturn nil, nil, errors.Wrapf(err, \"error reading [%d] bytes from file number [%d]\", length, s.fileNum)\n\t}\n\tblockPlacementInfo := &blockPlacementInfo{\n\t\tfileNum:          s.fileNum,\n\t\tblockStartOffset: s.currentOffset,\n\t\tblockBytesOffset: s.currentOffset + int64(n),\n\t}\n\ts.currentOffset += int64(n) + int64(length)\n\tlogger.Debugf(\"Returning blockbytes - length=[%d], placementInfo={%s}\", len(blockBytes), blockPlacementInfo)\n\treturn blockBytes, blockPlacementInfo, nil\n}\n\nfunc (s *blockfileStream) close() error {\n\treturn errors.WithStack(s.file.Close())\n}\n\n// /////////////////////////////////\n// blockStream functions\n// //////////////////////////////////","sourceCodeStart":112,"sourceCodeEnd":148,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/common/ledger/blkstorage/block_stream.go#L112-L148","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nblockBytes, err := readBlock(stream)\nif err != nil { return err }\n// after\nif _, err := readBlock(stream); err != nil {\n    if errors.Is(errors.Cause(err), io.ErrUnexpectedEOF) {\n        return recoverTornTail(file) // truncate after last complete block\n    }\n    return err\n}","handlingStrategy":"try-catch","validationCode":"info, err := os.Stat(blockfilePath)\nif err != nil || info.Size() < expectedMinSize {\n    return fmt.Errorf(\"file shorter than expected; torn write likely\")\n}","typeGuard":"func isShortRead(err error) bool {\n    c := errors.Cause(err)\n    return errors.Is(c, io.ErrUnexpectedEOF) || errors.Is(c, io.EOF)\n}","tryCatchPattern":"blk, err := stream.nextBlockBytes()\nif err != nil {\n    if isShortRead(err) {\n        logger.Warningf(\"torn block append detected: %v\", err)\n        return truncateAfterLastCompleteBlock(blockfilePath)\n    }\n    return err\n}","preventionTips":["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"],"tags":["fabric","ledger","io","torn-write"],"backgroundTag":"unexpected-eof-truncated-file","analyzedSha":"2736b63f8fd5932511d56fe68b7039d15977f7f6","analyzedAt":"2026-09-04T08:52:36.465Z","contentChangedAt":"2026-09-04T08:52:36.465Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}