{"record":{"id":"0f17a83100edfe74","repo":"hyperledger/fabric","slug":"chaincode-invocation-spec-did-not-contain-chaincod","errorCode":null,"errorMessage":"chaincode invocation spec did not contain chaincode spec","messagePattern":"chaincode invocation spec did not contain chaincode spec","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/endorser/msgvalidation.go","lineNumber":87,"sourceCode":"\t\treturn nil, errors.Errorf(\"ChaincodeHeaderExtension.ChaincodeId is nil\")\n\t}\n\n\tif chaincodeHdrExt.ChaincodeId.Name == \"\" {\n\t\treturn nil, errors.Errorf(\"ChaincodeHeaderExtension.ChaincodeId.Name is empty\")\n\t}\n\n\tcpp, err := protoutil.UnmarshalChaincodeProposalPayload(prop.Payload)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tcis, err := protoutil.UnmarshalChaincodeInvocationSpec(cpp.Input)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tif cis.ChaincodeSpec == nil {\n\t\treturn nil, errors.Errorf(\"chaincode invocation spec did not contain chaincode spec\")\n\t}\n\n\tif cis.ChaincodeSpec.Input == nil {\n\t\treturn nil, errors.Errorf(\"chaincode input did not contain any input\")\n\t}\n\n\tcppNoTransient := &peer.ChaincodeProposalPayload{Input: cpp.Input, TransientMap: nil}\n\tppBytes, err := proto.Marshal(cppNoTransient)\n\tif err != nil {\n\t\treturn nil, errors.WithMessage(err, \"could not marshal non-transient portion of payload\")\n\t}\n\n\t// TODO, this was preserved from the proputils stuff, but should this be BCCSP?\n\n\t// The proposal hash is the hash of the concatenation of:\n\t// 1) The serialized Channel Header object\n\t// 2) The serialized Signature Header object\n\t// 3) The hash of the part of the chaincode proposal payload that will go to the tx","sourceCodeStart":69,"sourceCodeEnd":105,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/core/endorser/msgvalidation.go#L69-L105","documentation":"UnpackProposal successfully decoded the ChaincodeInvocationSpec from the SignedProposal payload, but the decoded spec has a nil ChaincodeSpec field. This means the proposal's input was marshaled as a ChaincodeInvocationSpec wrapper with no actual chaincode spec inside. The endorser rejects it because there is no chaincode to invoke.","triggerScenarios":"Submitting a SignedProposal via ProcessProposal whose ChaincodeProposalPayload.Input unmarshals to a ChaincodeInvocationSpec with cis.ChaincodeSpec == nil — e.g. the client built the payload with an empty/zero ChaincodeInvocationSpec or deserialized and re-marshaled a spec incorrectly.","commonSituations":"Hand-crafted proposal payloads in tests or scripts, clients using low-level protobuf APIs instead of the fabric-sdk helper (e.g. newInvokeProposal), corrupted or truncated payloads, or SDK version mismatches that serialize the spec differently.","solutions":["Build the proposal payload with an SDK helper (fabprotos ChaincodeInvocationSpec populated with Type, ChaincodeId and Input) instead of constructing protobufs by hand.","Verify ChaincodeInvocationSpec.ChaincodeSpec is non-nil and ChaincodeSpec.ChaincodeId.Name is set before marshaling the payload.","Regenerate/refresh the proposal with the matching fabric-protos version used by the peer to avoid serialization drift."],"exampleFix":"// before\ninvocationSpec := &pb.ChaincodeInvocationSpec{}\npayload.Input, _ = proto.Marshal(invocationSpec)\n// after\ninvocationSpec := &pb.ChaincodeInvocationSpec{\n    ChaincodeSpec: &pb.ChaincodeSpec{\n        Type: pb.ChaincodeSpec_NODE,\n        ChaincodeId: &pb.ChaincodeID{Name: \"mycc\"},\n        Input: &pb.ChaincodeInput{Args: args},\n    },\n}\npayload.Input, _ = proto.Marshal(invocationSpec)","handlingStrategy":"validation","validationCode":"var cis pb.ChaincodeInvocationSpec\nif err := proto.Unmarshal(payload.Input, &cis); err != nil { return err }\nif cis.ChaincodeSpec == nil || cis.ChaincodeSpec.ChaincodeId == nil {\n    return errors.New(\"payload has no ChaincodeSpec\")\n}","typeGuard":"func hasChaincodeSpec(cis *pb.ChaincodeInvocationSpec) bool {\n    return cis != nil && cis.ChaincodeSpec != nil\n}","tryCatchPattern":null,"preventionTips":["Always build payloads via SDK proposal helpers","Unit-test payload marshaling before submitting to the peer","Pin fabric-protos versions between client and peer"],"tags":["hyperledger-fabric","endorser","proposal-validation","malformed-payload"],"backgroundTag":"chaincode-invocation-spec-missing","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"}