{"record":{"id":"4e183b0342307abb","repo":"hyperledger/fabric","slug":"response-payload-is-missing-extension","errorCode":null,"errorMessage":"response payload is missing extension","messagePattern":"response payload is missing extension","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"protoutil/txutils.go","lineNumber":38,"sourceCode":"// GetPayloads gets the underlying payload objects in a TransactionAction\nfunc GetPayloads(txActions *peer.TransactionAction) (*peer.ChaincodeActionPayload, *peer.ChaincodeAction, error) {\n\t// TODO: pass in the tx type (in what follows we're assuming the\n\t// type is ENDORSER_TRANSACTION)\n\tccPayload, err := UnmarshalChaincodeActionPayload(txActions.Payload)\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\n\tif ccPayload.Action == nil || ccPayload.Action.ProposalResponsePayload == nil {\n\t\treturn nil, nil, errors.New(\"no payload in ChaincodeActionPayload\")\n\t}\n\tpRespPayload, err := UnmarshalProposalResponsePayload(ccPayload.Action.ProposalResponsePayload)\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\n\tif pRespPayload.Extension == nil {\n\t\treturn nil, nil, errors.New(\"response payload is missing extension\")\n\t}\n\n\trespPayload, err := UnmarshalChaincodeAction(pRespPayload.Extension)\n\tif err != nil {\n\t\treturn ccPayload, nil, err\n\t}\n\treturn ccPayload, respPayload, nil\n}\n\n// GetEnvelopeFromBlock gets an envelope from a block's Data field.\nfunc GetEnvelopeFromBlock(data []byte) (*common.Envelope, error) {\n\t// Block always begins with an envelope\n\tvar err error\n\tenv := &common.Envelope{}\n\tif err = proto.Unmarshal(data, env); err != nil {\n\t\treturn nil, errors.Wrap(err, \"error unmarshalling Envelope\")\n\t}\n","sourceCodeStart":20,"sourceCodeEnd":56,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/protoutil/txutils.go#L20-L56","documentation":"After unmarshaling the ProposalResponsePayload, GetPayloads expects Extension to hold the marshaled ChaincodeAction (results/events). A nil Extension means the endorsement response had no chaincode action attached, so the function reports the missing extension.","triggerScenarios":"GetPayloads encounters a ProposalResponsePayload whose Extension field is nil — an endorser produced a response without the ChaincodeAction extension, or the payload bytes were corrupted/truncated so the extension was lost.","commonSituations":"Chaincode invocation that panicked/failed on the endorser yielding a bare response; custom endorsement code building ProposalResponsePayload without Extension; event-processing tools reading malformed proposal responses from blocks.","solutions":["Ensure endorsers populate ProposalResponsePayload.Extension with a marshaled ChaincodeAction (default fabric endorser path does this).","When constructing responses in tests/tools, marshal a ChaincodeAction into Extension.","Guard pRespPayload.Extension != nil before calling GetPayloads in block/event walkers and skip such transactions.","Verify block integrity — corruption can drop trailing fields like Extension."],"exampleFix":"// before\nrespPayload := &peer.ProposalResponsePayload{ProposalHash: hash}\n\n// after\naction := &peer.ChaincodeAction{Results: results, Events: events}\nrespPayload := &peer.ProposalResponsePayload{\n    ProposalHash: hash,\n    Extension:    protoutil.MarshalOrPanic(action),\n}","handlingStrategy":"validation","validationCode":"pRespPayload, err := protoutil.UnmarshalProposalResponsePayload(ccPayload.Action.ProposalResponsePayload)\nif err != nil {\n    return err\n}\nif pRespPayload.Extension == nil {\n    return errors.New(\"proposal response has no ChaincodeAction extension; skipping\")\n}","typeGuard":"func hasActionExtension(p *peer.ProposalResponsePayload) bool {\n    return p != nil && p.Extension != nil\n}","tryCatchPattern":"res, ev, err := protoutil.GetPayloads(txActions)\nif err != nil {\n    if strings.Contains(err.Error(), \"response payload is missing extension\") {\n        return nil // endorser returned no chaincode action; skip\n    }\n    return err\n}","preventionTips":["Use the standard fabric endorser path so Extension (ChaincodeAction) is always populated.","When crafting ProposalResponsePayload in tests, always marshal a ChaincodeAction into Extension.","In block explorers/event consumers, guard Extension presence before reading results/events.","Hash-verify stored blocks to detect truncation that could drop the extension field."],"tags":["fabric","proposal-response","extension","malformed-tx"],"backgroundTag":"missing-transaction-action-payload","analyzedSha":"2736b63f8fd5932511d56fe68b7039d15977f7f6","analyzedAt":"2026-09-04T08:52:36.465Z","contentChangedAt":"2026-09-04T08:52:36.465Z","schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}