hyperledger/fabric · error
nil version not supported
Error message
nil version not supported
What it means
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.
Source
Thrown at core/ledger/kvledger/txmgmt/statedb/statecouchdb/dbvalue_encoding.go:19
/*
Copyright IBM Corp. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/
package statecouchdb
import (
"encoding/base64"
"github.com/hyperledger/fabric/core/ledger/internal/version"
"github.com/pkg/errors"
"google.golang.org/protobuf/proto"
)
func encodeVersionAndMetadata(version *version.Height, metadata []byte) (string, error) {
if version == nil {
return "", errors.New("nil version not supported")
}
msg := &VersionAndMetadata{
Version: version.ToBytes(),
Metadata: metadata,
}
msgBytes, err := proto.Marshal(msg)
if err != nil {
return "", err
}
return base64.StdEncoding.EncodeToString(msgBytes), nil
}
func decodeVersionAndMetadata(encodedstr string) (*version.Height, []byte, error) {
persistedVersionAndMetadata, err := base64.StdEncoding.DecodeString(encodedstr)
if err != nil {
return nil, nil, err
}
versionAndMetadata := &VersionAndMetadata{}View on GitHub (pinned to 2736b63f8f)
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.
Example fix
// before batch.PutValAndMetadata(ns, key, value, metadata, nil) // after ver := version.NewHeight(blockNum, txNum) batch.PutValAndMetadata(ns, key, value, metadata, ver)
Defensive patterns
Strategy: type-guard
Validate before calling
if version == nil {
return fmt.Errorf("cannot persist key %s: version is nil; supply version.NewHeight(blockNum, txNum)", key)
} Type guard
func hasVersion(vv *statedb.VersionedValue) bool {
return vv != nil && vv.Version != nil
} Prevention
- 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
When it happens
Trigger: 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).
Common situations: 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.
Related errors
- error decoding the block number
- error decoding the data hash
- error decoding the previous hash
- error decoding the length of block data
- error decoding the transaction envelope
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/0c5e2ab4920ae6dd.
Report an issue: GitHub.