{"record":{"id":"c61d62f4bd6362f8","repo":"hyperledger/fabric","slug":"empty-proposalresponsepayload","errorCode":null,"errorMessage":"empty ProposalResponsePayload","messagePattern":"empty ProposalResponsePayload","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/tx/endorser/parser.go","lineNumber":87,"sourceCode":"\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)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tif len(proposalResponsePayload.Extension) == 0 {\n\t\treturn nil, errors.New(\"nil Extension\")\n\t}\n\n\tccAction, err := protoutil.UnmarshalChaincodeAction(proposalResponsePayload.Extension)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n","sourceCodeStart":69,"sourceCodeEnd":105,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/core/tx/endorser/parser.go#L69-L105","documentation":"The ChaincodeEndorsedAction exists but its ProposalResponsePayload bytes are empty. The ProposalResponsePayload carries the proposal hash, the chaincode result, and the response extension; without it the parser cannot extract the chaincode action or validate the read/write sets.","triggerScenarios":"UnmarshalEndorserTxAndValidate receives a transaction where ccActionPayload.Action.ProposalResponsePayload is a zero-length byte slice — the endorsed action was constructed without the proposal response payload.","commonSituations":"Transaction assembly skipping the proposal-response-payload marshaling step; endorsements copied without their payload; payload truncation in transit or storage.","solutions":["Populate ChaincodeEndorsedAction.ProposalResponsePayload with protoutil.MarshalOrPanic(&peer.ProposalResponsePayload{...}) before marshaling.","Regenerate the transaction using the standard SDK flow where the proposal response payload is always attached.","Verify byte integrity of the envelope along its storage/transport path."],"exampleFix":"// before\naction := &peer.ChaincodeEndorsedAction{Endorsements: endorsements} // PRP missing\n// after\naction := &peer.ChaincodeEndorsedAction{\n    ProposalResponsePayload: protoutil.MarshalOrPanic(prp),\n    Endorsements:            endorsements,\n}","handlingStrategy":"validation","validationCode":"func hasProposalResponsePayload(action *peer.ChaincodeEndorsedAction) bool {\n    return action != nil && len(action.ProposalResponsePayload) > 0\n}","typeGuard":"func hasPRP(a *peer.ChaincodeEndorsedAction) bool {\n    return a != nil && len(a.ProposalResponsePayload) > 0\n}","tryCatchPattern":"tx, err := parser.UnmarshalEndorserTxAndValidate(env)\nif err != nil {\n    if strings.Contains(err.Error(), \"empty ProposalResponsePayload\") {\n        // proposal response payload missing: regenerate from endorsement\n        return ErrBadTransaction\n    }\n    return err\n}","preventionTips":["Always attach marshaled ProposalResponsePayload to the endorsed action.","Copy endorsements together with their payload, never in isolation.","Check for byte truncation across serialization boundaries."],"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"}