hyperledger/fabric · error
error marshaling ChaincodeProposalPayload
Error message
error marshaling ChaincodeProposalPayload
What it means
The ChaincodeProposalPayload (marshaled invocation input + transient map) is serialized inside CreateChaincodeProposalWithTxIDNonceAndTransient; any proto.Marshal error is wrapped with this message. Practically it signals proto library/descriptor incompatibility or invalid input structure.
Source
Thrown at protoutil/proputils.go:76
// CreateChaincodeProposalWithTxIDNonceAndTransient creates a proposal from
// given input
func CreateChaincodeProposalWithTxIDNonceAndTransient(txid string, typ common.HeaderType, channelID string, cis *peer.ChaincodeInvocationSpec, nonce, creator []byte, transientMap map[string][]byte) (*peer.Proposal, string, error) {
ccHdrExt := &peer.ChaincodeHeaderExtension{ChaincodeId: cis.ChaincodeSpec.ChaincodeId}
ccHdrExtBytes, err := proto.Marshal(ccHdrExt)
if err != nil {
return nil, "", errors.Wrap(err, "error marshaling ChaincodeHeaderExtension")
}
cisBytes, err := proto.Marshal(cis)
if err != nil {
return nil, "", errors.Wrap(err, "error marshaling ChaincodeInvocationSpec")
}
ccPropPayload := &peer.ChaincodeProposalPayload{Input: cisBytes, TransientMap: transientMap}
ccPropPayloadBytes, err := proto.Marshal(ccPropPayload)
if err != nil {
return nil, "", errors.Wrap(err, "error marshaling ChaincodeProposalPayload")
}
// TODO: epoch is now set to zero. This must be changed once we
// get a more appropriate mechanism to handle it in.
var epoch uint64
hdr := &common.Header{
ChannelHeader: MarshalOrPanic(
&common.ChannelHeader{
Type: int32(typ),
TxId: txid,
Timestamp: timestamppb.Now(),
ChannelId: channelID,
Extension: ccHdrExtBytes,
Epoch: epoch,
},
),
SignatureHeader: MarshalOrPanic(View on GitHub (pinned to 2736b63f8f)
Solutions
- Reconcile fabric-protos-go and fabric versions (go mod tidy, single version per module graph)
- Rebuild the binary after `go clean -cache` to clear stale compiled proto descriptors
- Validate transient map keys are strings with []byte values (they are by type, so mostly inspect proto version)
Defensive patterns
Strategy: validation
Validate before calling
cpp := &peer.ChaincodeProposalPayload{Input: cisBytes, TransientMap: transientMap}
if _, err := proto.Marshal(cpp); err != nil {
return fmt.Errorf("proposal payload not marshalable (check proto runtime alignment): %w", err)
} Type guard
func payloadMarshalable(cpp *peer.ChaincodeProposalPayload) bool {
if cpp == nil { return false }
_, err := proto.Marshal(cpp)
return err == nil
} Try / catch
proposal, txid, err := protoutil.CreateChaincodeProposalWithTxIDAndTransient(txid, htype, ch, cis, creator, transient)
if err != nil {
if strings.Contains(err.Error(), "marshaling") {
return fmt.Errorf("proto incompatibility suspected: %w", err)
}
return err
} Prevention
- Single google.golang.org/protobuf version across the module graph
- Rebuild binaries after upgrading fabric-protos-go
- CI smoke test: create and marshal a full proposal in a unit test
When it happens
Trigger: Any wrapper call (CreateChaincodeProposalWithTransient, CreateChaincodeProposalWithTxIDAndTransient, CreateProposalFromCISAndTxid, ConstructSignedTxEnv) where marshaling &peer.ChaincodeProposalPayload{Input: cisBytes, TransientMap: transientMap} fails — only realistic with mismatched protobuf descriptors or a corrupted proto registry.
Common situations: Mixed fabric / fabric-protos-go versions in one binary; custom builds of protos; very large transient maps are NOT a cause (proto.Marshal has no size limit here) but corrupt keys could break expectations downstream.
Related errors
- could not marshal field %s
- failed to marshal updated readiness result
- failed to marshal args
- failed to marshal args
- error marshaling ChaincodeHeaderExtension
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/8740316b54e10b2c.
Report an issue: GitHub.