{"record":{"id":"e2fe8ad6e11e455e","repo":"hyperledger/fabric","slug":"recovery-for-db-s-not-possible-ledger-s-is","errorCode":null,"errorMessage":"recovery for DB [%s] not possible. Ledger [%s] is created from a snapshot. Last block in snapshot = [%d], DB needs block [%d] onward","messagePattern":"recovery for DB \\[(.+?)\\] not possible\\. Ledger \\[(.+?)\\] is created from a snapshot\\. Last block in snapshot = \\[(.+?)\\], DB needs block \\[(.+?)\\] onward","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"core/ledger/kvledger/kv_ledger.go","lineNumber":399,"sourceCode":"\t}\n\tlastBlockInBlockStore := info.Height - 1\n\trecoverables := []recoverable{l.txmgr}\n\tif l.historyDB != nil {\n\t\trecoverables = append(recoverables, l.historyDB)\n\t}\n\trecoverers := []*recoverer{}\n\tfor _, recoverable := range recoverables {\n\t\t// nextRequiredBlock is nothing but the nextBlockNum expected by the state DB.\n\t\t// In other words, the nextRequiredBlock is nothing but the height of stateDB.\n\t\trecoverFlag, nextRequiredBlock, err := recoverable.ShouldRecover(lastBlockInBlockStore)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\tif l.bootSnapshotMetadata != nil {\n\t\t\tlastBlockInSnapshot := l.bootSnapshotMetadata.LastBlockNumber\n\t\t\tif nextRequiredBlock <= lastBlockInSnapshot {\n\t\t\t\treturn errors.Errorf(\n\t\t\t\t\t\"recovery for DB [%s] not possible. Ledger [%s] is created from a snapshot. Last block in snapshot = [%d], DB needs block [%d] onward\",\n\t\t\t\t\trecoverable.Name(),\n\t\t\t\t\tl.ledgerID,\n\t\t\t\t\tlastBlockInSnapshot,\n\t\t\t\t\tnextRequiredBlock,\n\t\t\t\t)\n\t\t\t}\n\t\t}\n\n\t\tif nextRequiredBlock > lastBlockInBlockStore+1 {\n\t\t\tdbName := recoverable.Name()\n\t\t\treturn fmt.Errorf(\"the %s database [height=%d] is ahead of the block store [height=%d]. \"+\n\t\t\t\t\"This is possible when the %s database is not dropped after a ledger reset/rollback. \"+\n\t\t\t\t\"The %s database can safely be dropped and will be rebuilt up to block store height upon the next peer start\",\n\t\t\t\tdbName, nextRequiredBlock, lastBlockInBlockStore+1, dbName, dbName)\n\t\t}\n\t\tif recoverFlag {\n\t\t\trecoverers = append(recoverers, &recoverer{nextRequiredBlock, recoverable})","sourceCodeStart":381,"sourceCodeEnd":417,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/core/ledger/kvledger/kv_ledger.go#L381-L417","documentation":"syncStateAndHistoryDBWithBlockstore returns this when a ledger was created from a snapshot and a state/history database is missing blocks earlier than the snapshot boundary. The DB needs blocks from nextRequiredBlock onward, but the block store (from the snapshot) only contains blocks up to lastBlockInSnapshot, so recovery by replay is impossible. Fabric refuses to proceed rather than produce an inconsistent database.","triggerScenarios":"Peer started with a snapshot-created ledger (bootSnapshotMetadata set) while the state DB or history DB height requires a block number <= the snapshot's last block number (e.g. the DB was deleted/reset, or an older DB was moved in).","commonSituations":"Operator deletes only the state or history DB directory under ledgersData of a snapshot-bootstrapped peer; restoring an old state DB backup onto a snapshot-based ledger; misconfigured ledgersData where DBs and blockstore come from different sources.","solutions":["Drop ALL ledger databases (state, history, bookkeeping) so they rebuild from the snapshot's last block via snapshot verification data","Restore the complete, consistent ledgersData set that matches the snapshot","If pre-snapshot data is required, resync from genesis instead of using a snapshot"],"exampleFix":"// before: only stateDB deleted -> recovery impossible\n// after: remove all DBs under ledgersData of the snapshot ledger\n//   rm -rf /var/hyperledger/production/ledgersData/state\n//   rm -rf /var/hyperledger/production/ledgersData/history\n//   rm -rf /var/hyperledger/production/ledgersData/bookkeeper\n// then restart peer (rebuilds from snapshot)","handlingStrategy":"validation","validationCode":"// Before mixing snapshot ledgers with DB dirs, ensure DB heights are consistent:\n// if the ledger came from a snapshot, ALL DBs must be empty or at snapshot height\nif ledgerCreatedFromSnapshot && (stateDBExists || historyDBExists) {\n    // drop state, history, and bookkeeper dirs so they rebuild from the snapshot\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never delete only one DB under ledgersData of a snapshot-bootstrapped peer; drop all DBs together","Do not restore older state/history DB backups onto snapshot-based ledgers","Keep blockstore and DBs from the same provenance (same snapshot or same backup)"],"tags":["hyperledger-fabric","ledger","snapshot","recovery"],"backgroundTag":"ledger-snapshot-recovery-impossible","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"}