hyperledger/fabric · error

failed reading directory %s

Error message

failed reading directory %s

What it means

ListInstalledChaincodes scans the peer's chaincode install directory with ls(dir) to enumerate installed chaincode packages. If the directory exists (os.Stat passed) but cannot be read — permissions, I/O error, or it is not actually a directory — the read error is wrapped with this message.

Source

Thrown at core/common/ccprovider/ccprovider.go:203

	return cccdspack, nil
}

// DirEnumerator enumerates directories
type DirEnumerator func(string) ([]os.DirEntry, error)

// ChaincodeExtractor extracts chaincode from a given path
type ChaincodeExtractor func(ccNameVersion string, path string, getHasher GetHasher) (CCPackage, error)

// ListInstalledChaincodes retrieves the installed chaincodes
func (cifs *CCInfoFSImpl) ListInstalledChaincodes(dir string, ls DirEnumerator, ccFromPath ChaincodeExtractor) ([]chaincode.InstalledChaincode, error) {
	var chaincodes []chaincode.InstalledChaincode
	if _, err := os.Stat(dir); err != nil && os.IsNotExist(err) {
		return nil, nil
	}
	files, err := ls(dir)
	if err != nil {
		return nil, errors.Wrapf(err, "failed reading directory %s", dir)
	}

	for _, f := range files {
		// Skip directories, we're only interested in normal files
		if f.IsDir() {
			continue
		}
		// A chaincode file name is of the type "name.version"
		// We're only interested in the name.
		// Skip files that don't adhere to the file naming convention of "A.B"
		i := strings.Index(f.Name(), ".")
		if i == -1 {
			ccproviderLogger.Info("Skipping", f.Name(), "because of missing separator '.'")
			continue
		}
		ccName := f.Name()[:i]      // Everything before the separator
		ccVersion := f.Name()[i+1:] // Everything after the separator

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Fix filesystem permissions so the peer process can read the chaincode install directory
  2. Confirm the configured install path is a real directory ('ls -ld') and not a file or broken symlink/mount
  3. Check the wrapped underlying error for I/O details (EACCES, ENOTDIR, etc.)
  4. Restart or repair storage backing the peer's data directory if the filesystem is damaged

Example fix

// before
sudo chmod 700 /var/hyperledger/production/chaincodes
// after
sudo chown -R peer:peer /var/hyperledger/production/chaincodes && sudo chmod 755 /var/hyperledger/production/chaincodes
Defensive patterns

Strategy: try-catch

Validate before calling

dir := "/var/hyperledger/production/chaincodes"
fi, err := os.Stat(dir)
if err != nil || !fi.IsDir() {
    return fmt.Errorf("invalid chaincode dir %s", dir)
}
if _, err := os.ReadDir(dir); err != nil {
    return fmt.Errorf("cannot read chaincode dir: %w", err)
}

Type guard

func isReadableDir(path string) bool {
    fi, err := os.Stat(path)
    return err == nil && fi.IsDir()
}

Try / catch

chaincodes, err := ccprovider.ListInstalledChaincodes()
if err != nil {
    if strings.Contains(err.Error(), "failed reading directory") {
        // recover: fix permissions or recreate dir, then retry once
        return retryAfterDirRepair(err)
    }
    return err
}

Prevention

When it happens

Trigger: Calling ListInstalledChaincodes when ls(dir) returns an error, e.g. the chaincode install path is unreadable by the peer process or is a file rather than a directory.

Common situations: Directory permissions changed after security hardening; the install path misconfigured to a file or mount point that disappeared; disk/NFS errors on the peer host.

Related errors


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