hyperledger/fabric · error

no payload in ChaincodeActionPayload

Error message

no payload in ChaincodeActionPayload

What it means

GetPayloads walks a Transaction's ChaincodeActionPayload to extract the proposal response payloads (results and events) for a transaction. If ccPayload.Action or its ProposalResponsePayload is nil, the transaction action carries no results, and this error signals the missing payload.

Source

Thrown at protoutil/txutils.go:30

	b64 "encoding/base64"

	"github.com/hyperledger/fabric-protos-go-apiv2/common"
	"github.com/hyperledger/fabric-protos-go-apiv2/peer"
	"github.com/pkg/errors"
	"google.golang.org/protobuf/proto"
)

// GetPayloads gets the underlying payload objects in a TransactionAction
func GetPayloads(txActions *peer.TransactionAction) (*peer.ChaincodeActionPayload, *peer.ChaincodeAction, error) {
	// TODO: pass in the tx type (in what follows we're assuming the
	// type is ENDORSER_TRANSACTION)
	ccPayload, err := UnmarshalChaincodeActionPayload(txActions.Payload)
	if err != nil {
		return nil, nil, err
	}

	if ccPayload.Action == nil || ccPayload.Action.ProposalResponsePayload == nil {
		return nil, nil, errors.New("no payload in ChaincodeActionPayload")
	}
	pRespPayload, err := UnmarshalProposalResponsePayload(ccPayload.Action.ProposalResponsePayload)
	if err != nil {
		return nil, nil, err
	}

	if pRespPayload.Extension == nil {
		return nil, nil, errors.New("response payload is missing extension")
	}

	respPayload, err := UnmarshalChaincodeAction(pRespPayload.Extension)
	if err != nil {
		return ccPayload, nil, err
	}
	return ccPayload, respPayload, nil
}

// GetEnvelopeFromBlock gets an envelope from a block's Data field.

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Check the transaction validation code/status on the envelope — invalid transactions often lack full action payloads; skip them when walking blocks.
  2. Verify the endorsing peers returned a ProposalResponsePayload and that the endorser path recorded it in the Transaction.
  3. Re-unmarshal the block/envelope from a trusted source to rule out corruption.
  4. If you only need results, guard for nil Action/ProposalResponsePayload and skip instead of treating it as fatal.

Example fix

// before
res, ev, err := protoutil.GetPayloads(txActions)

// after
if txActions == nil || txActions.Payload == nil {
    return nil // nothing to process
}
ccPayload, _ := protoutil.UnmarshalChaincodeActionPayload(txActions.Payload)
if ccPayload.Action == nil || ccPayload.Action.ProposalResponsePayload == nil {
    return nil // invalid/empty action, skip
}
Defensive patterns

Strategy: validation

Validate before calling

ccPayload, err := protoutil.UnmarshalChaincodeActionPayload(txActions.Payload)
if err != nil {
    return err
}
if ccPayload.Action == nil || ccPayload.Action.ProposalResponsePayload == nil {
    return errors.New("transaction has no endorsed action payload; skipping")
}

Type guard

func hasActionPayload(cc *peer.ChaincodeActionPayload) bool {
    return cc != nil && cc.Action != nil && cc.Action.ProposalResponsePayload != nil
}

Try / catch

res, ev, err := protoutil.GetPayloads(txActions)
if err != nil {
    if strings.Contains(err.Error(), "no payload in ChaincodeActionPayload") {
        return nil // invalid or empty transaction; skip in block walkers
    }
    return err
}

Prevention

When it happens

Trigger: Calling GetPayloads (via GetActionFromEnvelopeMsg or getKeyModificationFromTran) on a transaction whose ChaincodeEndorsedAction has no ProposalResponsePayload — endorsements recorded without a proposal response, or truncated/corrupted transaction payloads.

Common situations: Inspecting blocks containing invalid/filtered transactions that were never fully endorsed; chaincode actions created by paths that only record events; corruption in block data consumed by event tools or explorers.

Related errors


AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04). Data as JSON: /api/errors/3a33f5a3be0cdae0. Report an issue: GitHub.