hyperledger/fabric · error

error unmarshalling TxReadWriteSet

Error message

error unmarshalling TxReadWriteSet

What it means

UnmarshalTxReadWriteSet wraps proto.Unmarshal failures for rwset.TxReadWriteSet bytes. It means the supplied bytes are not a valid TxReadWriteSet protobuf message. rwsetDifference calls it, so RW-set comparison tooling hits it when one side has corrupted or wrongly-encoded read-write set bytes.

Source

Thrown at protoutil/unmarshalers.go:179

// UnmarshalChaincodeActionPayload unmarshals bytes to a ChaincodeActionPayload
func UnmarshalChaincodeActionPayload(capBytes []byte) (*peer.ChaincodeActionPayload, error) {
	cap := &peer.ChaincodeActionPayload{}
	err := proto.Unmarshal(capBytes, cap)
	return cap, errors.Wrap(err, "error unmarshalling ChaincodeActionPayload")
}

// UnmarshalChaincodeProposalPayload unmarshals bytes to a ChaincodeProposalPayload
func UnmarshalChaincodeProposalPayload(bytes []byte) (*peer.ChaincodeProposalPayload, error) {
	cpp := &peer.ChaincodeProposalPayload{}
	err := proto.Unmarshal(bytes, cpp)
	return cpp, errors.Wrap(err, "error unmarshalling ChaincodeProposalPayload")
}

// UnmarshalTxReadWriteSet unmarshals bytes to a TxReadWriteSet
func UnmarshalTxReadWriteSet(bytes []byte) (*rwset.TxReadWriteSet, error) {
	rws := &rwset.TxReadWriteSet{}
	err := proto.Unmarshal(bytes, rws)
	return rws, errors.Wrap(err, "error unmarshalling TxReadWriteSet")
}

// UnmarshalKVRWSet unmarshals bytes to a KVRWSet
func UnmarshalKVRWSet(bytes []byte) (*kvrwset.KVRWSet, error) {
	rws := &kvrwset.KVRWSet{}
	err := proto.Unmarshal(bytes, rws)
	return rws, errors.Wrap(err, "error unmarshalling KVRWSet")
}

// UnmarshalHashedRWSet unmarshals bytes to a HashedRWSet
func UnmarshalHashedRWSet(bytes []byte) (*kvrwset.HashedRWSet, error) {
	hrws := &kvrwset.HashedRWSet{}
	err := proto.Unmarshal(bytes, hrws)
	return hrws, errors.Wrap(err, "error unmarshalling HashedRWSet")
}

// UnmarshalSignaturePolicy unmarshals bytes to a SignaturePolicyEnvelope
func UnmarshalSignaturePolicy(bytes []byte) (*common.SignaturePolicyEnvelope, error) {

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Ensure the bytes are the marshalled TxReadWriteSet (e.g. proto.Marshal of the whole message), not a sub-message or JSON encoding
  2. Check for empty input before calling; an empty slice will fail to unmarshal
  3. Regenerate the RW set bytes with the same fabric-protos version used for unmarshalling
  4. If unmarshal fails during comparison, treat the sets as differing/invalid rather than retrying

Example fix

// before
rws, err := protoutil.UnmarshalTxReadWriteSet(nil)
// after
if len(rwsetBytes) == 0 { return errors.New("empty rwset bytes") }
rws, err := protoutil.UnmarshalTxReadWriteSet(rwsetBytes)
Defensive patterns

Strategy: validation

Validate before calling

func hasRWSetBytes(b []byte) bool { return len(b) > 0 }

Type guard

func safeUnmarshalTxRWS(b []byte) (rws *rwset.TxReadWriteSet, ok bool) {
    rws, err := protoutil.UnmarshalTxReadWriteSet(b)
    return rws, err == nil && rws != nil
}

Try / catch

rws, err := protoutil.UnmarshalTxReadWriteSet(b)
if err != nil {
    return nil, fmt.Errorf("rwset comparison aborted, undecodable input: %w", err)
}

Prevention

When it happens

Trigger: Calling UnmarshalTxReadWriteSet with nil/empty bytes, bytes of a TxRwSet's internal NsRwSets, an already-unmarshalled struct serialized with json instead of proto, or cross-version proto encodings.

Common situations: Comparing RW sets between the simulated ledger and committed transactions, state validation tooling, or tests feeding hand-built byte slices.

Related errors


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