{"record":{"id":"b0db229e96190fb3","repo":"hyperledger/fabric","slug":"cannot-open-ledger-s-ledger-status-is-s","errorCode":null,"errorMessage":"cannot open ledger [%s], ledger status is [%s]","messagePattern":"cannot open ledger \\[(.+?)\\], ledger status is \\[(.+?)\\]","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/ledger/kvledger/kv_ledger_provider.go","lineNumber":330,"sourceCode":"\tif cleanupErr == nil {\n\t\treturn creationErr\n\t}\n\treturn errors.WithMessage(cleanupErr, creationErr.Error())\n}\n\n// Open implements the corresponding method from interface ledger.PeerLedgerProvider\nfunc (p *Provider) Open(ledgerID string) (ledger.PeerLedger, error) {\n\tlogger.Debugf(\"Open() opening kvledger: %s\", ledgerID)\n\t// Check the ID store to ensure that the chainId/ledgerId exists\n\tledgerMetadata, err := p.idStore.getLedgerMetadata(ledgerID)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif ledgerMetadata == nil {\n\t\treturn nil, errors.Errorf(\"cannot open ledger [%s], ledger does not exist\", ledgerID)\n\t}\n\tif ledgerMetadata.Status != msgs.Status_ACTIVE {\n\t\treturn nil, errors.Errorf(\"cannot open ledger [%s], ledger status is [%s]\", ledgerID, ledgerMetadata.Status)\n\t}\n\n\tbootSnapshotMetadata, err := snapshotMetadataFromProto(ledgerMetadata.BootSnapshotMetadata)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn p.open(ledgerID, bootSnapshotMetadata, false)\n}\n\nfunc (p *Provider) open(ledgerID string, bootSnapshotMetadata *SnapshotMetadata, initializingFromSnapshot bool) (ledger.PeerLedger, error) {\n\t// Get the block store for a chain/ledger\n\tblockStore, err := p.blkStoreProvider.Open(ledgerID)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tpvtdataStore, err := p.pvtdataStoreProvider.OpenStore(ledgerID)\n\tif err != nil {\n\t\treturn nil, err","sourceCodeStart":312,"sourceCodeEnd":348,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/core/ledger/kvledger/kv_ledger_provider.go#L312-L348","documentation":"After loading the ledger's metadata from the idStore, Open checks metadata.Status; if it is not msgs.Status_ACTIVE the provider refuses to open the ledger and reports the current status. Non-ACTIVE statuses (UNDER_CONSTRUCTION, UNDER_DELETION) indicate a previous create/delete operation did not finish — the peer likely crashed mid-operation — and the ledger is in a partial state that must not be used.","triggerScenarios":"ledger.Provider.Open(ledgerID) where the idStore metadata for ledgerID exists but Status == msgs.Status_UNDER_CONSTRUCTION or msgs.Status_UNDER_DELETION: a peer crash/interrupt during ledger creation (channel join) or during channel unjoin left the status flag set.","commonSituations":"Peer killed (OOM, power loss, container restart) in the middle of joining a channel; a channel unjoin command that aborted midway; manually copied idStore from a peer that had a partially created ledger.","solutions":["Restart the peer: NewProvider -> deletePartialLedgers detects UNDER_CONSTRUCTION/UNDER_DELETION ledgers at launch and deletes them, after which the channel can be re-joined cleanly.","If the ledger should exist, re-run the channel join after the partial ledger is purged.","If the status is UNDER_DELETION, let the deletion complete (peer launch finishes it) rather than forcing the ledger open.","For an emergency manual repair, update the idStore metadata Status to ACTIVE only after verifying all sub-databases are consistent — otherwise prefer re-creation from a snapshot or genesis block."],"exampleFix":"// before: forcing open a partially-created ledger fails\nlgr, err := provider.Open(\"mychannel\") // status is UNDER_CONSTRUCTION\n\n// after: restart peer so deletePartialLedgers purges it, then re-join\n// peer restart -> \"A partial ledger was identified at peer launch... will be deleted\"\n// peer channel join -b mychannel.block\nlgr, err := provider.Open(\"mychannel\") // status is now ACTIVE","handlingStrategy":"try-catch","validationCode":"func isOpenable(metadataStatus msgs.Status) bool {\n\treturn metadataStatus == msgs.Status_ACTIVE\n}","typeGuard":null,"tryCatchPattern":"lgr, err := provider.Open(ledgerID)\nif err != nil && strings.Contains(err.Error(), \"ledger status is\") {\n\t// non-ACTIVE ledger: restart peer so deletePartialLedgers purges it, then re-join\n\treturn fmt.Errorf(\"ledger %s is in a partial state; restart peer and re-join the channel\", ledgerID)\n}\nif err != nil {\n\treturn err\n}","preventionTips":["Use graceful peer shutdown (SIGTERM, not SIGKILL) so create/delete operations finish.","Avoid restarting peers mid channel-join or mid unjoin; serialize these operations in automation.","After abnormal shutdown, check peer logs for 'partial ledger was identified' before opening ledgers.","Monitor ledger status after crash recovery and alert on non-ACTIVE states."],"tags":["ledger","ledger-status","crash-recovery","go"],"backgroundTag":"ledger-under-construction","analyzedSha":"2736b63f8fd5932511d56fe68b7039d15977f7f6","analyzedAt":"2026-09-04T08:52:36.465Z","contentChangedAt":"2026-09-04T08:52:36.465Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}