{"record":{"id":"0c5e2ab4920ae6dd","repo":"hyperledger/fabric","slug":"nil-version-not-supported","errorCode":null,"errorMessage":"nil version not supported","messagePattern":"nil version not supported","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/ledger/kvledger/txmgmt/statedb/statecouchdb/dbvalue_encoding.go","lineNumber":19,"sourceCode":"/*\nCopyright IBM Corp. All Rights Reserved.\n\nSPDX-License-Identifier: Apache-2.0\n*/\n\npackage statecouchdb\n\nimport (\n\t\"encoding/base64\"\n\n\t\"github.com/hyperledger/fabric/core/ledger/internal/version\"\n\t\"github.com/pkg/errors\"\n\t\"google.golang.org/protobuf/proto\"\n)\n\nfunc encodeVersionAndMetadata(version *version.Height, metadata []byte) (string, error) {\n\tif version == nil {\n\t\treturn \"\", errors.New(\"nil version not supported\")\n\t}\n\tmsg := &VersionAndMetadata{\n\t\tVersion:  version.ToBytes(),\n\t\tMetadata: metadata,\n\t}\n\tmsgBytes, err := proto.Marshal(msg)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\treturn base64.StdEncoding.EncodeToString(msgBytes), nil\n}\n\nfunc decodeVersionAndMetadata(encodedstr string) (*version.Height, []byte, error) {\n\tpersistedVersionAndMetadata, err := base64.StdEncoding.DecodeString(encodedstr)\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\tversionAndMetadata := &VersionAndMetadata{}","sourceCodeStart":1,"sourceCodeEnd":37,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/core/ledger/kvledger/txmgmt/statedb/statecouchdb/dbvalue_encoding.go#L1-L37","documentation":"encodeVersionAndMetadata serializes a version.Height into the CouchDB value envelope. It refuses a nil version because a stored state entry must carry block/tx provenance; a nil version would produce an unusable record that cannot be reconstructed during reads.","triggerScenarios":"keyValToCouchDoc encoding a VersionedValue whose Version field is nil — e.g. a batch entry built with a nil *version.Height, or code paths that insert values without a block height context (also hit directly in the encode/decode unit test).","commonSituations":"Custom batch construction in tests or tooling that forgets to set Version; calling internal serialization helpers outside the normal commit flow where the version is computed from the block height.","solutions":["Pass a valid *version.Height (from the committing block's Height) instead of nil.","When constructing VersionedValue manually, set version via version.NewHeight(blockNum, txNum).","Trace where the nil version originates — usually the caller of PutValAndMetadata or a batch builder — and supply the current block height.","If this is pure metadata-only data, use an API path that does not require versioning."],"exampleFix":"// before\nbatch.PutValAndMetadata(ns, key, value, metadata, nil)\n// after\nver := version.NewHeight(blockNum, txNum)\nbatch.PutValAndMetadata(ns, key, value, metadata, ver)","handlingStrategy":"type-guard","validationCode":"if version == nil {\n  return fmt.Errorf(\"cannot persist key %s: version is nil; supply version.NewHeight(blockNum, txNum)\", key)\n}","typeGuard":"func hasVersion(vv *statedb.VersionedValue) bool {\n  return vv != nil && vv.Version != nil\n}","tryCatchPattern":null,"preventionTips":["Always derive version from the committing block height, never hardcode nil","Use version.NewHeight rather than manual struct construction","Cover batch-building code with a test that asserts non-nil versions"],"tags":["couchdb","versioning","serialization","ledger"],"backgroundTag":"nil-version-not-supported","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"}