hyperledger/fabric · error
nil payload header
Error message
nil payload header
What it means
validateProtoAndConstructTxEnv requires payload.Header to be non-nil. A Payload whose Header is unset cannot be routed (no channel, type, or txid), so it is rejected with BAD_PAYLOAD. This check follows successful Payload unmarshalling.
Source
Thrown at core/tx/processor_factory.go:71
if len(txenv.Payload) == 0 {
return nil, &tx.InvalidErr{
ActualErr: errors.New("nil envelope payload"),
ValidationCode: peer.TxValidationCode_BAD_PAYLOAD,
}
}
payload, err := protoutil.UnmarshalPayload(txenv.Payload)
if err != nil {
return nil, &tx.InvalidErr{
ActualErr: err,
ValidationCode: peer.TxValidationCode_BAD_PAYLOAD,
}
}
if payload.Header == nil {
return nil, &tx.InvalidErr{
ActualErr: errors.New("nil payload header"),
ValidationCode: peer.TxValidationCode_BAD_PAYLOAD,
}
}
if len(payload.Header.ChannelHeader) == 0 {
return nil, &tx.InvalidErr{
ActualErr: errors.New("nil payload channel header"),
ValidationCode: peer.TxValidationCode_BAD_PAYLOAD,
}
}
chdr, err := protoutil.UnmarshalChannelHeader(payload.Header.ChannelHeader)
if err != nil {
return nil, &tx.InvalidErr{
ActualErr: err,
ValidationCode: peer.TxValidationCode_BAD_PAYLOAD,
}
}View on GitHub (pinned to 2736b63f8f)
Solutions
- Set payload.Header = &common.Header{ChannelHeader: chdrBytes, SignatureHeader: shdrBytes} before marshaling.
- Use protoutil.MakeChannelHeader + protoutil.MakePayloadHeader helpers to build a complete header.
- Check payload.Header != nil before submit/marshal in client code.
Example fix
// before
payload := &common.Payload{Data: cceBytes}
// after
payload := &common.Payload{Header: protoutil.MakePayloadHeader(chdr, shdr), Data: cceBytes} Defensive patterns
Strategy: validation
Validate before calling
if payload.Header == nil { return errors.New("payload header is nil") } Type guard
func hasHeader(p *common.Payload) bool { return p != nil && p.Header != nil } Prevention
- Always construct payloads with protoutil.MakePayloadHeader.
- After building a payload, assert Header, ChannelHeader, and SignatureHeader are all set before marshal.
- Review any code path that constructs common.Payload manually.
When it happens
Trigger: Unmarshalled payload bytes that describe only Data with no Header — e.g. payload := &common.Payload{Data: data} marshaled without setting Header.
Common situations: Hand-assembled payloads in tests; payloads built before ChannelHeader/SignatureHeader construction failed or was skipped; older clients producing header-less payloads after a protocol change.
Related errors
- nil envelope payload
- nil payload channel header
- error unmarshalling ChaincodeHeaderExtension
- nil ChaincodeId in header extension
- nil ChaincodeId in ChaincodeAction
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/93995c792fbe0efa.
Report an issue: GitHub.