{"record":{"id":"8871c1b0dcaded24","repo":"hyperledger/fabric","slug":"empty-chaincodeactionpayload","errorCode":null,"errorMessage":"empty ChaincodeActionPayload","messagePattern":"empty ChaincodeActionPayload","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/tx/endorser/parser.go","lineNumber":74,"sourceCode":"\t}\n\n\ttx, err := protoutil.UnmarshalTransaction(txenv.Data)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tif len(tx.GetActions()) != 1 {\n\t\treturn nil, errors.Errorf(\"only one transaction action is supported, %d were present\", len(tx.GetActions()))\n\t}\n\n\ttxAction := tx.GetActions()[0]\n\n\tif txAction == nil {\n\t\treturn nil, errors.New(\"nil action\")\n\t}\n\n\tif len(txAction.Payload) == 0 {\n\t\treturn nil, errors.New(\"empty ChaincodeActionPayload\")\n\t}\n\n\tccActionPayload, err := protoutil.UnmarshalChaincodeActionPayload(txAction.Payload)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tif ccActionPayload.Action == nil {\n\t\treturn nil, errors.New(\"nil ChaincodeEndorsedAction\")\n\t}\n\n\tif len(ccActionPayload.Action.ProposalResponsePayload) == 0 {\n\t\treturn nil, errors.New(\"empty ProposalResponsePayload\")\n\t}\n\n\tproposalResponsePayload, err := protoutil.UnmarshalProposalResponsePayload(\n\t\tccActionPayload.Action.ProposalResponsePayload,\n\t)","sourceCodeStart":56,"sourceCodeEnd":92,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/core/tx/endorser/parser.go#L56-L92","documentation":"The TransactionAction's Payload bytes are empty, so there is no ChaincodeActionPayload to unmarshal. A valid endorser transaction action must carry a serialized ChaincodeActionPayload containing the proposal hash, endorsements, and response. An empty payload means the action was never populated.","triggerScenarios":"UnmarshalEndorserTxAndValidate receives a transaction where tx.Actions[0].Payload is a zero-length byte slice — the TransactionAction struct was created but its Payload field was never assigned.","commonSituations":"Custom transaction builders skipping the ChaincodeActionPayload step; truncation of protobuf bytes during transport/storage; mock/test envelopes used in production paths.","solutions":["Populate TransactionAction.Payload with protoutil.MarshalOrPanic(&peer.ChaincodeActionPayload{...}) before building the envelope.","Regenerate the transaction through the standard SDK submit flow (proposal -> endorse -> assemble).","Check for byte truncation in the path that serialized/transmitted the envelope."],"exampleFix":"// before\naction := &common.TransactionAction{} // Payload empty\n// after\naction := &common.TransactionAction{\n    Payload: protoutil.MarshalOrPanic(chaincodeActionPayload),\n}","handlingStrategy":"validation","validationCode":"func hasActionPayload(tx *common.Transaction) bool {\n    a := tx.GetActions()[0]\n    return a != nil && len(a.Payload) > 0\n}","typeGuard":"func hasPayload(a *common.TransactionAction) bool {\n    return a != nil && len(a.Payload) > 0\n}","tryCatchPattern":"tx, err := parser.UnmarshalEndorserTxAndValidate(env)\nif err != nil {\n    if strings.Contains(err.Error(), \"empty ChaincodeActionPayload\") {\n        // action payload missing: regenerate transaction via SDK flow\n        return ErrBadTransaction\n    }\n    return err\n}","preventionTips":["Always marshal ChaincodeActionPayload into TransactionAction.Payload.","Verify envelope byte integrity after any storage or transport step.","Avoid using mock/test envelopes outside of tests."],"tags":["hyperledger-fabric","transaction","validation"],"backgroundTag":"malformed-envelope-payload","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"}