hyperledger/fabric · error · ErrLedgerAlreadyOpened
ledger already opened
Error message
ledger already opened
What it means
ErrLedgerAlreadyOpened is a sentinel error returned by LedgerMgr.OpenLedger when the requested channel's ledger is already present in the manager's openedLedgers map, since each ledger may only be opened once per manager instance. It prevents duplicate handles to the same underlying ledger, which would corrupt state coordination.
Source
Thrown at core/ledger/ledgermgmt/ledger_mgmt.go:29
"fmt"
"sync"
"github.com/hyperledger/fabric-lib-go/common/flogging"
"github.com/hyperledger/fabric-lib-go/common/metrics"
"github.com/hyperledger/fabric-protos-go-apiv2/common"
pb "github.com/hyperledger/fabric-protos-go-apiv2/peer"
"github.com/hyperledger/fabric/core/common/ccprovider"
"github.com/hyperledger/fabric/core/ledger"
"github.com/hyperledger/fabric/core/ledger/cceventmgmt"
"github.com/hyperledger/fabric/core/ledger/kvledger"
"github.com/hyperledger/fabric/internal/fileutil"
"github.com/pkg/errors"
)
var logger = flogging.MustGetLogger("ledgermgmt")
// ErrLedgerAlreadyOpened is thrown by a CreateLedger call if a ledger with the given id is already opened
var ErrLedgerAlreadyOpened = errors.New("ledger already opened")
// ErrLedgerMgmtNotInitialized is thrown when ledger mgmt is used before initializing this
var ErrLedgerMgmtNotInitialized = errors.New("ledger mgmt should be initialized before using")
// LedgerMgr manages ledgers for all channels
type LedgerMgr struct {
creationLock sync.Mutex
joinBySnapshotStatus *pb.JoinBySnapshotStatus
lock sync.Mutex
openedLedgers map[string]ledger.PeerLedger
ledgerProvider ledger.PeerLedgerProvider
ebMetadataProvider MetadataProvider
}
type MetadataProvider interface {
PackageMetadata(ccid string) ([]byte, error)View on GitHub (pinned to 2736b63f8f)
Solutions
- Track which ledger ids are already opened and reuse the existing PeerLedger handle instead of calling OpenLedger again.
- Compare against the exported sentinel with errors.Is(err, ledgermgmt.ErrLedgerAlreadyOpened) and treat it as 'already have it' rather than a fatal failure.
- Call CloseLedger for the open ledger before attempting to reopen it, if reopening is genuinely required.
Example fix
// before
l, err := ledgerMgr.OpenLedger(chanID)
if err != nil {
return err
}
// after
l, err := ledgerMgr.OpenLedger(chanID)
if err != nil {
if errors.Is(err, ledgermgmt.ErrLedgerAlreadyOpened) {
l = existingHandles[chanID] // reuse cached handle
return nil
}
return err
} Defensive patterns
Strategy: type-guard
Validate before calling
// keep a set of already-opened ledgers
if _, open := openedLedgers[chanID]; open {
return openedLedgers[chanID], nil // skip OpenLedger
} Type guard
func IsLedgerAlreadyOpened(err error) bool {
return errors.Is(err, ledgermgmt.ErrLedgerAlreadyOpened)
} Try / catch
lgr, err := ledgerMgr.OpenLedger(chanID)
if err != nil {
if errors.Is(err, ledgermgmt.ErrLedgerAlreadyOpened) {
return cachedLedgerHandle(chanID), nil
}
return err
} Prevention
- Cache PeerLedger handles per channel instead of reopening
- Call CloseLedger before reopening a ledger
- Guard concurrent OpenLedger calls for the same channel with a mutex or singleflight
- Use errors.Is against the exported sentinel, never string matching
When it happens
Trigger: Calling OpenLedger(id) twice for the same ledger/channel id without closing the first instance; a channel created via CreateLedger and then opened again; test code calling OpenLedger on an already-open ledger.
Common situations: Applications caching ledger handles then re-invoking OpenLedger on channel join or reconnection; race between two goroutines opening the same channel; event handlers firing OpenLedger redundantly after the ledger was already opened at creation.
Related errors
- ledger mgmt should be initialized before using
- error decoding the block number
- error decoding the data hash
- error decoding the previous hash
- error decoding the length of block data
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/fd9bcd63f923bec9.
Report an issue: GitHub.