hyperledger/fabric · error

error reading dir

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.

Solutions

  1. Verify the ledger root directory exists and is readable by the peer process (check ledgersData/chains/<chainID>)
  2. Fix permissions/ownership on the ledger directory (match the peer's runtime user)
  3. Correct peer.fileSystemPath or mount the expected volume
  4. 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

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


AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04). Data as JSON: /api/errors/b34b8d6c40c49291. Report an issue: GitHub.

Appendix: 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, err

View on GitHub (pinned to 2736b63f8f)