{"record":{"id":"7010b0764ef6e35d","repo":"hyperledger/fabric","slug":"error-marshaling-chaincodeinvocationspec","errorCode":null,"errorMessage":"error marshaling ChaincodeInvocationSpec","messagePattern":"error marshaling ChaincodeInvocationSpec","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"protoutil/proputils.go","lineNumber":70,"sourceCode":"\tif txid == \"\" {\n\t\ttxid = ComputeTxID(nonce, creator)\n\t}\n\n\treturn CreateChaincodeProposalWithTxIDNonceAndTransient(txid, typ, channelID, cis, nonce, creator, transientMap)\n}\n\n// CreateChaincodeProposalWithTxIDNonceAndTransient creates a proposal from\n// given input\nfunc CreateChaincodeProposalWithTxIDNonceAndTransient(txid string, typ common.HeaderType, channelID string, cis *peer.ChaincodeInvocationSpec, nonce, creator []byte, transientMap map[string][]byte) (*peer.Proposal, string, error) {\n\tccHdrExt := &peer.ChaincodeHeaderExtension{ChaincodeId: cis.ChaincodeSpec.ChaincodeId}\n\tccHdrExtBytes, err := proto.Marshal(ccHdrExt)\n\tif err != nil {\n\t\treturn nil, \"\", errors.Wrap(err, \"error marshaling ChaincodeHeaderExtension\")\n\t}\n\n\tcisBytes, err := proto.Marshal(cis)\n\tif err != nil {\n\t\treturn nil, \"\", errors.Wrap(err, \"error marshaling ChaincodeInvocationSpec\")\n\t}\n\n\tccPropPayload := &peer.ChaincodeProposalPayload{Input: cisBytes, TransientMap: transientMap}\n\tccPropPayloadBytes, err := proto.Marshal(ccPropPayload)\n\tif err != nil {\n\t\treturn nil, \"\", errors.Wrap(err, \"error marshaling ChaincodeProposalPayload\")\n\t}\n\n\t// TODO: epoch is now set to zero. This must be changed once we\n\t// get a more appropriate mechanism to handle it in.\n\tvar epoch uint64\n\n\thdr := &common.Header{\n\t\tChannelHeader: MarshalOrPanic(\n\t\t\t&common.ChannelHeader{\n\t\t\t\tType:      int32(typ),\n\t\t\t\tTxId:      txid,\n\t\t\t\tTimestamp: timestamppb.Now(),","sourceCodeStart":52,"sourceCodeEnd":88,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/protoutil/proputils.go#L52-L88","documentation":"Same function as above: after the header extension, the ChaincodeInvocationSpec (the chaincode call with arguments) is protobuf-marshaled and failures are wrapped with this message. A failure again points to malformed/nil input or proto incompatibility rather than runtime state.","triggerScenarios":"CreateChaincodeProposalWithTxIDNonceAndTransient (and wrappers CreateChaincodeProposalWithTransient, CreateChaincodeProposalWithTxIDAndTransient, CreateProposalFromCISAndTxid) receiving a cis containing fields the registered proto cannot marshal — typically a fabric-protos package version mismatch or corrupted deep fields like Input bytes.","commonSituations":"Dependency drift where peer proto descriptors changed between fabric versions; passing hand-built ChaincodeInvocationSpec with invalid nested messages; unregistered custom extensions.","solutions":["Verify go.mod has one consistent github.com/hyperledger/fabric-protos-go version (go mod tidy / go mod graph)","Build cis via peer.ChaincodeSpec factories rather than hand-assembling bytes","Confirm cis.Input args are valid [][]byte (nil elements are fine for proto3, but check for corrupt data)","Re-run with a minimal ChaincodeInvocationSpec to isolate which field breaks marshaling"],"exampleFix":"// before\ncis := &peer.ChaincodeInvocationSpec{} // no ChaincodeSpec, drifted proto\ncis.ProtoSpec = nil\n// after\ngo get github.com/hyperledger/fabric-protos-go@v0.x.y\ncis := &peer.ChaincodeInvocationSpec{ChaincodeSpec: &peer.ChaincodeSpec{Type: peer.ChaincodeSpec_GOLANG, ChaincodeId: ccid, Input: &peer.ChaincodeInput{Args: [][]byte{[]byte(\"invoke\")}}}}","handlingStrategy":"validation","validationCode":"if cis == nil { return errors.New(\"cis is nil\") }\nif cis.ChaincodeSpec == nil { return errors.New(\"cis.ChaincodeSpec is nil\") }\nif _, err := proto.Marshal(cis); err != nil { return fmt.Errorf(\"CIS not marshalable: %w\", err) }","typeGuard":"func cisMarshalable(cis *peer.ChaincodeInvocationSpec) bool {\n\tif cis == nil { return false }\n\t_, err := proto.Marshal(cis)\n\treturn err == nil\n}","tryCatchPattern":"cisBytes, err := proto.Marshal(cis)\nif err != nil { return fmt.Errorf(\"invalid invocation spec, check proto versions: %w\", err) }","preventionTips":["Run `go mod graph | grep fabric-protos` to detect version conflicts","Prefer protoutil helper constructors over hand-assembled proto messages","Add a startup smoke test that marshals a representative ChaincodeInvocationSpec"],"tags":["fabric","protobuf","marshal","chaincode-invocation-spec"],"backgroundTag":"protobuf-marshal-failed","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"}