hyperledger/fabric · critical
failed to read ledger directory %s
Error message
failed to read ledger directory %s
What it means
NewProvider for the file-based blockstore stats the chains directory (conf.getChainsDir(), typically under FileLedger/ledgerData). If os.Stat fails with anything other than NotExist — e.g. permission denied or an I/O error — the error is wrapped with this message and provider creation aborts. Note that NotExist is tolerated and the directory is created.
Source
Thrown at common/ledger/blkstorage/blockstore_provider.go:74
stats *stats
}
// NewProvider constructs a filesystem based block store provider
func NewProvider(conf *Conf, indexConfig *IndexConfig, metricsProvider metrics.Provider) (*BlockStoreProvider, error) {
dbConf := &leveldbhelper.Conf{
DBPath: conf.getIndexDir(),
ExpectedFormat: dataFormatVersion(indexConfig),
}
p, err := leveldbhelper.NewProvider(dbConf)
if err != nil {
return nil, err
}
dirPath := conf.getChainsDir()
if _, err := os.Stat(dirPath); err != nil {
if !os.IsNotExist(err) { // NotExist is the only permitted error type
return nil, errors.Wrapf(err, "failed to read ledger directory %s", dirPath)
}
logger.Info("Creating new file ledger directory at", dirPath)
if err = os.MkdirAll(dirPath, 0o755); err != nil {
return nil, errors.Wrapf(err, "failed to create ledger directory: %s", dirPath)
}
}
stats := newStats(metricsProvider)
return &BlockStoreProvider{conf, indexConfig, p, stats}, nil
}
// Open opens a block store for given ledgerid.
// If a blockstore is not existing, this method creates one
// This method should be invoked only once for a particular ledgerid
func (p *BlockStoreProvider) Open(ledgerid string) (*BlockStore, error) {
indexStoreHandle := p.leveldbProvider.GetDBHandle(ledgerid)
return newBlockStore(ledgerid, p.conf, p.indexConfig, indexStoreHandle, p.stats)View on GitHub (pinned to 2736b63f8f)
Solutions
- Run the wrapped cause (os.Stat error) to see the OS-level reason (permission denied vs I/O).
- Fix permissions on the ledger directory: chown/chmod so the peer process user has rwx.
- Check that the volume/mount is writable and not full (df, mount ro/rw).
- Verify the peer's fileLedger location config matches the directory actually provisioned.
- If migrating containers/k8s, align the securityContext runAsUser/FSGroup with the directory owner.
Example fix
// before: peer fails to start with unreadable ledger dir // after: provision correct ownership before starting // $ sudo chown -R 7051:7051 /var/hyperledger/production/ledgersData // $ chmod -R u+rwX /var/hyperledger/production/ledgersData
Defensive patterns
Strategy: validation
Validate before calling
dirPath := filepath.Join(ledgerDataPath, "chains")
if fi, err := os.Stat(dirPath); err != nil && !os.IsNotExist(err) {
return fmt.Errorf("cannot access ledger dir %s: %v — fix permissions/mount before starting peer", dirPath, err)
} Try / catch
provider, err := blkstorage.NewProvider(conf)
if err != nil && strings.Contains(err.Error(), "failed to read ledger directory") {
return fmt.Errorf("check ownership/permissions/mount of the ledger directory: %w", err)
}
if err != nil { return err } Prevention
- Provision the ledger directory with correct ownership (peer UID, e.g. chown 7051) before startup.
- Verify volumes are mounted read-write and have free space in container/K8s deployments.
- Keep securityContext runAsUser/FSGroup aligned with the ledger directory owner.
- Test the ledger path with a simple stat/write check in your startup health script.
When it happens
Trigger: Starting the peer (or calling NewProvider/openBlockStorage) when the ledger directory exists but is unreadable: wrong ownership/permissions, an EACCES/EPERM/EIO from the filesystem, or the path being an unreadable mount.
Common situations: Peer running as non-root against a ledgerData dir owned by another user, read-only or full mount, container volume permission mismatch after image upgrade, Kubernetes securityContext UID changes.
Related errors
- error opening block file reader for file %s
- failed to create ledger directory: %s
- error cleaning up transient files
- error opening block file %s
- error seeking block file [%s] to startOffset [%d]
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/d6f16b909268ae62.
Report an issue: GitHub.