hyperledger/fabric · error
nil payload data
Error message
nil payload data
What it means
unmarshalEndorserTx parses an envelope into an EndorserTx. After unmarshaling the envelope, the transaction payload bytes (txenv.Data) are absent. Hyperledger Fabric requires the envelope to carry a serialized Transaction containing at least one action; an empty Data field means the envelope is malformed or not an endorser transaction. The library fails fast here instead of returning a uselessly empty transaction.
Source
Thrown at core/tx/endorser/parser.go:55
Version int32
Epoch uint64
Nonce []byte
}
func unmarshalEndorserTx(txenv *tx.Envelope) (*EndorserTx, error) {
if len(txenv.ChannelHeader.Extension) == 0 {
return nil, errors.New("empty header extension")
}
hdrExt, err := protoutil.UnmarshalChaincodeHeaderExtension(
txenv.ChannelHeader.Extension,
)
if err != nil {
return nil, err
}
if len(txenv.Data) == 0 {
return nil, errors.New("nil payload data")
}
tx, err := protoutil.UnmarshalTransaction(txenv.Data)
if err != nil {
return nil, err
}
if len(tx.GetActions()) != 1 {
return nil, errors.Errorf("only one transaction action is supported, %d were present", len(tx.GetActions()))
}
txAction := tx.GetActions()[0]
if txAction == nil {
return nil, errors.New("nil action")
}
if len(txAction.Payload) == 0 {View on GitHub (pinned to 2736b63f8f)
Solutions
- Verify the envelope is an endorser transaction envelope (Data non-empty) before calling UnmarshalEndorserTxAndValidate.
- Re-create the envelope using protoutil.CreateTxEnvelope / the normal submit path instead of hand-building it.
- If the envelope comes from a block, confirm it is an endorser tx (type TRANSACTION), not a config tx.
Example fix
// before
env := &common.Envelope{Signature: sig} // Data never set
_, err := parser.UnmarshalEndorserTxAndValidate(env)
// after
payload := protoutil.MarshalOrPanic(&common.Payload{Data: txBytes})
env := &common.Envelope{Payload: payload, Signature: sig}
_, err := parser.UnmarshalEndorserTxAndValidate(env) Defensive patterns
Strategy: validation
Validate before calling
func hasTxData(env *common.Envelope) bool {
payload := &common.Payload{}
if proto.Unmarshal(env.GetPayload(), payload) != nil {
return false
}
return len(payload.GetData()) > 0
}
// call before: if !hasTxData(env) { skip UnmarshalEndorserTxAndValidate } Type guard
func isValidEndorserEnvelope(env *common.Envelope) bool {
return env != nil && len(env.Payload) > 0
} Try / catch
tx, err := parser.UnmarshalEndorserTxAndValidate(env)
if err != nil {
if strings.Contains(err.Error(), "nil payload data") {
// handle non-endorser/malformed envelope: skip or re-route
return nil
}
return err
} Prevention
- Use protoutil.CreateTxEnvelope rather than hand-building envelopes.
- Check envelope type (TRANSACTION vs CONFIG) before parsing.
- Log the envelope type/length when this parse fails to diagnose input source.
When it happens
Trigger: Calling UnmarshalEndorserTxAndValidate with an envelope whose TransactionActions/Data field is empty — e.g. an envelope created from a config transaction, a nil transaction, or a hand-built envelope where the Transaction was never assigned to Data.
Common situations: Passing a config/block-envelope rather than an endorser tx envelope; constructing protoutil envelopes manually and forgetting to set Data; corruption or truncation in storage/transport that dropped the payload.
Related errors
- invalid chaincode ID
- invalid header type %s
- only one transaction action is supported, %d were present
- nil action
- empty ChaincodeActionPayload
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/0d6dd3a0677942aa.
Report an issue: GitHub.