hyperledger/fabric · critical

unexpected data version - cannot upgrade data format for pvt

Error message

unexpected data version - cannot upgrade data format for pvtdatastore from %s to %s

What it means

CheckAndConstructHashedIndex inspects the pvtdatastore's recorded format version; it can only upgrade data version 1.0 to 2.5 by retroactively building the hashed index. If the stored version is neither the old version nor the current one, the on-disk private data store is in an unrecognized state and the provider refuses to open it rather than corrupting data.

Source

Thrown at core/ledger/pvtdatastorage/retroactive_hashed_index.go:43

func CheckAndConstructHashedIndex(storePath string, ledgerIDs []string) error {
	info, err := leveldbhelper.RetrieveDataFormatInfo(storePath)
	if err != nil {
		return err
	}

	if info.IsDBEmpty || info.FormatVerison == currentDataVersion {
		return nil
	}

	if info.FormatVerison == previousDataVersion {
		if err := constructHashedIndex(storePath, ledgerIDs); err != nil {
			return err
		}
		return nil
	}

	return errors.Errorf("unexpected data version - cannot upgrade data format for pvtdatastore from %s to %s", info.FormatVerison, currentDataVersion)
}

// constructHashedIndex creates the HashedIndex entries for the private data keys and at the end sets the
// data format version to the current version (2.5)
func constructHashedIndex(storePath string, ledgerIDs []string) error {
	p, err := leveldbhelper.NewProvider(
		&leveldbhelper.Conf{
			DBPath:         storePath,
			ExpectedFormat: previousDataVersion,
		},
	)
	if err != nil {
		return err
	}

	defer p.Close()

	for _, l := range ledgerIDs {

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Run the peer with a binary whose version is >= the version that wrote the datastore (never downgrade across the data-version change).
  2. Restore the pvtdatastore from a consistent backup taken with the same version, or delete and rebuild it (e.g. re-join the channel) if the data is dispensable.
  3. If the version record is corrupt, rebuild the private data store from block/pvtdata sources or a fresh snapshot join.

Example fix

// before: peer binary v2.4 opening a datastore written by v2.5
// after: upgrade the peer binary to match/exceed the datastore version
// (or rebuild: stop peer, move pvtdatastore aside, re-join channel by snapshot/genesis)
Defensive patterns

Strategy: validation

Validate before calling

info, err := pvtdatastore.ReadFormatVersion(storePath)
if err != nil { return err }
if info.FormatVerison != "1.0" && info.FormatVerison != currentDataVersion {
    return fmt.Errorf("unsupported pvtdatastore version %s; use matching peer binary", info.FormatVerison)
}

Try / catch

if err := CheckAndConstructHashedIndex(storePath, ledgerIDs); err != nil {
    if strings.Contains(err.Error(), "unexpected data version") {
        // halt startup; require matching binary version or rebuild of pvtdatastore
    }
    return err
}

Prevention

When it happens

Trigger: Opening a peer whose pvtdatastore directory reports a FormatVerison other than the legacy 1.0 or the current version — e.g. a datastore from a newer/older Fabric version, a corrupted version record, or a partially upgraded datastore.

Common situations: Downgrading a peer to a Fabric version whose currentDataVersion is lower than what the datastore was written with; restoring the pvtdatastore from an unknown/mixed backup; corruption of the store's metadata after a crash.

Related errors


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