hyperledger/fabric · error

config history for ledger [%s] exists. Incremental import is

Error message

config history for ledger [%s] exists. Incremental import is not supported. Remove the existing ledger data before retry

What it means

ImportFromSnapshot refuses to import snapshot collection-config history into a ledger whose config history DB already contains data. Incremental imports are unsupported by design to keep snapshot-derived history consistent.

Source

Thrown at core/ledger/confighistory/mgr.go:131

// ledgerID from the snapshot files present in the dir
func (m *Mgr) ImportFromSnapshot(ledgerID string, dir string) error {
	exist, _, err := fileutil.FileExists(filepath.Join(dir, snapshotDataFileName))
	if err != nil {
		return err
	}
	if !exist {
		// when the ledger being bootstrapped never had a private data collection for
		// any chaincode, the snapshot files associated with the confighistory store
		// will not be present in the snapshot directory. Hence, we can return early
		return nil
	}
	db := m.dbProvider.getDB(ledgerID)
	empty, err := db.IsEmpty()
	if err != nil {
		return err
	}
	if !empty {
		return errors.New(fmt.Sprintf(
			"config history for ledger [%s] exists. Incremental import is not supported. "+
				"Remove the existing ledger data before retry",
			ledgerID,
		))
	}

	configMetadata, err := snapshot.OpenFile(filepath.Join(dir, snapshotMetadataFileName), snapshotFileFormat)
	if err != nil {
		return err
	}
	defer configMetadata.Close()

	numCollectionConfigs, err := configMetadata.DecodeUVarInt()
	if err != nil {
		return err
	}
	collectionConfigData, err := snapshot.OpenFile(filepath.Join(dir, snapshotDataFileName), snapshotFileFormat)
	if err != nil {

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Remove the existing ledger data directory for that ledgerID (e.g. ledgersData/ledgerProvider under the peer's filesystem path) before re-importing
  2. Restore the full ledger from the snapshot (snapshot import is a one-shot operation on a fresh ledger)
  3. Verify the ledgerID — you may be accidentally importing into an existing ledger rather than a new one
  4. Ensure automation doesn't re-run the import step after a successful first pass

Example fix

# before
peer node rebuild-dbs   # ledger data still present, import fails
# after
rm -rf /var/hyperledger/production/ledgersData/ledgerProvider/<ledgerID>  # or wipe ledger dir
peer node rebuild-dbs && re-run snapshot import on the empty ledger
Defensive patterns

Strategy: validation

Validate before calling

db := dbProvider.getDB(ledgerID)
empty, err := db.IsEmpty()
if err != nil { return err }
if !empty {
    return fmt.Errorf("ledger %s already has config history; skip import or wipe data", ledgerID)
}
return mgr.ImportFromSnapshot(ledgerID, newHashFunc, dir)

Type guard

func canImportSnapshot(dbProvider *dbProvider, ledgerID string) bool {
    empty, err := dbProvider.getDB(ledgerID).IsEmpty()
    return err == nil && empty
}

Try / catch

err := mgr.ImportFromSnapshot(ledgerID, hashFunc, dir)
if err != nil && strings.Contains(err.Error(), "Incremental import is not supported") {
    // wipe the ledger's config history dir, then retry once on the empty ledger
}

Prevention

When it happens

Trigger: ImportFromSnapshot (via CreateFromSnapshot) is invoked for a ledgerID whose confighistory LevelDB directory is non-empty — e.g. re-running snapshot import against an existing ledger, or a ledger that ran normally and then had a snapshot import attempted.

Common situations: Operator retries a failed snapshot restore without clearing ledger data; pointing a snapshot import at a live/pre-existing ledgerID; running the import twice (idempotency mistake).

Related errors


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