hyperledger/fabric · error
error reading dir %s
Error message
error reading dir %s
What it means
Wraps the os.ReadDir error when retrieveLastFileSuffix cannot list the block storage root directory. This function scans for the highest-numbered blockfile_<n> to build blockfilesInfo; without a directory listing the ledger cannot determine its file layout. Returned by constructBlockfilesInfo, resetToGenesisBlk, and rollback paths.
Source
Thrown at common/ledger/blkstorage/blockfile_helper.go:139
}
defer s.close()
bb, err := s.nextBlockBytes()
if err != nil {
return 0, err
}
blockInfo, err := extractSerializedBlockInfo(bb)
if err != nil {
return 0, err
}
return blockInfo.blockHeader.Number, nil
}
func retrieveLastFileSuffix(rootDir string) (int, error) {
logger.Debugf("retrieveLastFileSuffix()")
biggestFileNum := -1
filesInfo, err := os.ReadDir(rootDir)
if err != nil {
return -1, errors.Wrapf(err, "error reading dir %s", rootDir)
}
for _, fileInfo := range filesInfo {
name := fileInfo.Name()
if fileInfo.IsDir() || !isBlockFileName(name) {
logger.Debugf("Skipping File name = %s", name)
continue
}
fileSuffix := strings.TrimPrefix(name, blockfilePrefix)
fileNum, err := strconv.Atoi(fileSuffix)
if err != nil {
return -1, err
}
if fileNum > biggestFileNum {
biggestFileNum = fileNum
}
}
logger.Debugf("retrieveLastFileSuffix() - biggestFileNum = %d", biggestFileNum)
return biggestFileNum, errView on GitHub (pinned to 2736b63f8f)
Solutions
- Verify the ledger root directory exists and is readable by the peer process (check ledgersData/chains/<chainID>)
- Fix permissions/ownership on the ledger directory (match the peer's runtime user)
- Correct peer.fileSystemPath or mount the expected volume
- If the directory was deleted, restore from backup or re-create the chain (re-join/re-sync)
Example fix
// before
filesInfo, err := os.ReadDir(rootDir)
if err != nil { return -1, err }
// after: validate up front
if info, err := os.Stat(rootDir); err != nil || !info.IsDir() {
return -1, fmt.Errorf("ledger dir %s missing or not a directory", rootDir)
}
filesInfo, err := os.ReadDir(rootDir)
if err != nil { return -1, errors.Wrapf(err, "error reading dir %s", rootDir) } Defensive patterns
Strategy: validation
Validate before calling
info, err := os.Stat(rootDir)
if err != nil {
return fmt.Errorf("ledger root %s missing: %w", rootDir, err)
}
if !info.IsDir() {
return fmt.Errorf("%s is not a directory", rootDir)
}
if f, err := os.Open(rootDir); err != nil {
return fmt.Errorf("ledger root %s not readable: %w", rootDir, err)
} else {
f.Close()
} Try / catch
suffix, err := retrieveLastFileSuffix(rootDir)
if err != nil {
if os.IsNotExist(errors.Cause(err)) {
return initializeEmptyLedgerDir(rootDir)
}
return err
} Prevention
- Verify peer.fileSystemPath and volume mounts at startup
- Run the peer as one consistent user; chown ledger dirs after image upgrades
- Never mount the ledger volume read-only
- Alert on deletion of the ledgersData directory tree
When it happens
Trigger: retrieveLastFileSuffix(rootDir) calls os.ReadDir(rootDir); failure means the rootDir does not exist, is not readable (permissions), or an I/O error occurs.
Common situations: peer.fileSystemPath misconfigured (wrong mount, volume not attached); ledger directory deleted while the peer runs; permission problems after running the peer as different users (root-created files unreadable by the peer user); read-only mounted volume.
Understand the failure class
Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.
Related errors
- error opening block file %s
- error seeking block file [%s] to startOffset [%d]
- error getting block file stat
- snapshot dir %s is empty
- unexpected end of blockfile
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/b34b8d6c40c49291.
Report an issue: GitHub.