{"record":{"id":"65aa93d6458cce09","repo":"hyperledger/fabric","slug":"chaincode-spec-is-nil","errorCode":null,"errorMessage":"chaincode spec is nil","messagePattern":"chaincode spec is nil","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"protoutil/proputils.go","lineNumber":431,"sourceCode":"\terr := proto.Unmarshal(proposalBytes, proposal)\n\tif err != nil {\n\t\treturn \"\", errors.WithMessage(err, \"could not unmarshal proposal\")\n\t}\n\n\tproposalPayload := &peer.ChaincodeProposalPayload{}\n\terr = proto.Unmarshal(proposal.Payload, proposalPayload)\n\tif err != nil {\n\t\treturn \"\", errors.WithMessage(err, \"could not unmarshal chaincode proposal payload\")\n\t}\n\n\tcis := &peer.ChaincodeInvocationSpec{}\n\terr = proto.Unmarshal(proposalPayload.Input, cis)\n\tif err != nil {\n\t\treturn \"\", errors.WithMessage(err, \"could not unmarshal chaincode invocation spec\")\n\t}\n\n\tif cis.ChaincodeSpec == nil {\n\t\treturn \"\", errors.Errorf(\"chaincode spec is nil\")\n\t}\n\n\tif cis.ChaincodeSpec.ChaincodeId == nil {\n\t\treturn \"\", errors.Errorf(\"chaincode id is nil\")\n\t}\n\n\treturn cis.ChaincodeSpec.ChaincodeId.Name, nil\n}\n","sourceCodeStart":413,"sourceCodeEnd":440,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/protoutil/proputils.go#L413-L440","documentation":"InvokedChaincodeName parses a SignedProposal's payload into a ChaincodeInvocationSpec and returns the invoked chaincode's name. After unmarshaling the proposal payload, if the ChaincodeInvocationSpec has a nil ChaincodeSpec there is no invoked chaincode to identify, so the function returns this error.","triggerScenarios":"Submitting a SignedProposal whose payload.Input unmarshals to a ChaincodeInvocationSpec with no ChaincodeSpec set — e.g. a proposal built with an empty ChaincodeInvocationSpec or with only the decorator/args fields left unset.","commonSituations":"Manually assembled proposals in tests missing ChaincodeSpec; corrupted or truncated payload bytes that decode but leave fields empty; SDK calls that send an invoke proposal with an unset spec after failed construction.","solutions":["Populate the ChaincodeInvocationSpec's ChaincodeSpec (including ChaincodeId and Input) before signing and sending the proposal.","Validate the proposal construction path in your SDK/CLI so cis.ChaincodeSpec is always set for invoke proposals.","If the proposal came from the wire, treat it as malformed and reject it; re-fetch or have the client rebuild the transaction.","Check proto marshaling of the upstream proposal — ensure the right message type was serialized into Payload.Input."],"exampleFix":"// before\ncis := &peer.ChaincodeInvocationSpec{}\n\n// after\ncis := &peer.ChaincodeInvocationSpec{\n    ChaincodeSpec: &peer.ChaincodeSpec{\n        Type:        peer.ChaincodeSpec_NODE,\n        ChaincodeId: &peer.ChaincodeID{Name: \"mycc\"},\n        Input:       &peer.ChaincodeInput{Args: args},\n    },\n}","handlingStrategy":"validation","validationCode":"var cis peer.ChaincodeInvocationSpec\nif err := proto.Unmarshal(proposalPayload.Input, &cis); err != nil {\n    return err\n}\nif cis.ChaincodeSpec == nil {\n    return errors.New(\"proposal has no ChaincodeSpec\")\n}","typeGuard":"func hasChaincodeSpec(cis *peer.ChaincodeInvocationSpec) bool {\n    return cis != nil && cis.ChaincodeSpec != nil\n}","tryCatchPattern":"name, err := protoutil.InvokedChaincodeName(signedProp)\nif err != nil {\n    return fmt.Errorf(\"malformed proposal (no chaincode spec): %w\", err)\n}","preventionTips":["Construct invoke proposals with an SDK helper that always sets ChaincodeInvocationSpec.ChaincodeSpec.","Reject proposals at the ingress path when the payload cannot fully unmarshal with a spec.","Test hand-built proposals against InvokedChaincodeName in CI.","Log the proposal channel header type alongside the error to distinguish malformed client traffic."],"tags":["fabric","proposal","chaincode","malformed-payload"],"backgroundTag":"nil-chaincode-spec","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"}