{"record":{"id":"7ce8b40e6d8acd6e","repo":"hyperledger/fabric","slug":"unexpected-data-version-cannot-upgrade-data-form","errorCode":null,"errorMessage":"unexpected data version - cannot upgrade data format for pvtdatastore from %s to %s","messagePattern":"unexpected data version - cannot upgrade data format for pvtdatastore from (.+?) to (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"core/ledger/pvtdatastorage/retroactive_hashed_index.go","lineNumber":43,"sourceCode":"\nfunc CheckAndConstructHashedIndex(storePath string, ledgerIDs []string) error {\n\tinfo, err := leveldbhelper.RetrieveDataFormatInfo(storePath)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif info.IsDBEmpty || info.FormatVerison == currentDataVersion {\n\t\treturn nil\n\t}\n\n\tif info.FormatVerison == previousDataVersion {\n\t\tif err := constructHashedIndex(storePath, ledgerIDs); err != nil {\n\t\t\treturn err\n\t\t}\n\t\treturn nil\n\t}\n\n\treturn errors.Errorf(\"unexpected data version - cannot upgrade data format for pvtdatastore from %s to %s\", info.FormatVerison, currentDataVersion)\n}\n\n// constructHashedIndex creates the HashedIndex entries for the private data keys and at the end sets the\n// data format version to the current version (2.5)\nfunc constructHashedIndex(storePath string, ledgerIDs []string) error {\n\tp, err := leveldbhelper.NewProvider(\n\t\t&leveldbhelper.Conf{\n\t\t\tDBPath:         storePath,\n\t\t\tExpectedFormat: previousDataVersion,\n\t\t},\n\t)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tdefer p.Close()\n\n\tfor _, l := range ledgerIDs {","sourceCodeStart":25,"sourceCodeEnd":61,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/core/ledger/pvtdatastorage/retroactive_hashed_index.go#L25-L61","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Run the peer with a binary whose version is >= the version that wrote the datastore (never downgrade across the data-version change).","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.","If the version record is corrupt, rebuild the private data store from block/pvtdata sources or a fresh snapshot join."],"exampleFix":"// before: peer binary v2.4 opening a datastore written by v2.5\n// after: upgrade the peer binary to match/exceed the datastore version\n// (or rebuild: stop peer, move pvtdatastore aside, re-join channel by snapshot/genesis)","handlingStrategy":"validation","validationCode":"info, err := pvtdatastore.ReadFormatVersion(storePath)\nif err != nil { return err }\nif info.FormatVerison != \"1.0\" && info.FormatVerison != currentDataVersion {\n    return fmt.Errorf(\"unsupported pvtdatastore version %s; use matching peer binary\", info.FormatVerison)\n}","typeGuard":null,"tryCatchPattern":"if err := CheckAndConstructHashedIndex(storePath, ledgerIDs); err != nil {\n    if strings.Contains(err.Error(), \"unexpected data version\") {\n        // halt startup; require matching binary version or rebuild of pvtdatastore\n    }\n    return err\n}","preventionTips":["Never downgrade the peer binary below the version that wrote the datastore.","Keep consistent backups of pvtdatastore taken by the same Fabric version.","Check release notes for pvtdatastore data-version changes before upgrading/restoring."],"tags":["ledger","pvtdatastore","data-version","migration","fabric"],"backgroundTag":"data-version-mismatch","analyzedSha":"2736b63f8fd5932511d56fe68b7039d15977f7f6","analyzedAt":"2026-09-04T08:52:36.465Z","contentChangedAt":"2026-09-04T08:52:36.465Z","schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}