hyperledger/fabric · error

no header in payload

Error message

no header in payload

What it means

After the payload decodes, unwrapReqFromEnvelop checks that payload.Header is set and returns 'no header in payload' when it is nil. Every fabric transaction payload must carry a common.Header (containing ChannelHeader and SignatureHeader); without it the request cannot be attributed to a channel or client. This is a structural validation error, not a deserialization failure.

Source

Thrown at orderer/consensus/smartbft/util.go:257

}

func (ri *RequestInspector) unwrapReq(req []byte) (*request, error) {
	envelope, err := protoutil.UnmarshalEnvelope(req)
	if err != nil {
		return nil, err
	}

	return ri.unwrapReqFromEnvelop(envelope)
}

func (ri *RequestInspector) unwrapReqFromEnvelop(envelope *cb.Envelope) (*request, error) {
	payload := &cb.Payload{}
	if err := proto.Unmarshal(envelope.Payload, payload); err != nil {
		return nil, errors.Wrap(err, "failed unmarshalling payload")
	}

	if payload.Header == nil {
		return nil, errors.Errorf("no header in payload")
	}

	sigHdr := &cb.SignatureHeader{}
	if err := proto.Unmarshal(payload.Header.SignatureHeader, sigHdr); err != nil {
		return nil, err
	}

	if len(payload.Header.ChannelHeader) == 0 {
		return nil, errors.New("no channel header in payload")
	}

	chdr, err := protoutil.UnmarshalChannelHeader(payload.Header.ChannelHeader)
	if err != nil {
		return nil, errors.WithMessage(err, "error unmarshalling channel header")
	}

	return &request{
		chHdr:    chdr,

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Construct payloads with protoutil with headers: use protoutil.CreateSignedEnvelope / MakeChannelHeader + MakeSignatureHeader and attach via MakePayload
  2. Validate client-side before submitting: decode the envelope and assert Payload.Header != nil
  3. Reject/fix the producer of header-less envelopes; check configtxlator decode output
  4. If this comes from network input, treat it as a malformed-request attack and drop it

Example fix

// before
payload := &cb.Payload{Data: data} // Header nil
// after
chdr := protoutil.MakeChannelHeader(cb.HeaderType_ENDORSER_TRANSACTION, 0, channelID, 0)
sigHdr, _ := protoutil.MakeSignatureHeader(serializedCreator, nonce)
pHeader := protoutil.MakePayloadHeader(chdr, sigHdr)
payload := &cb.Payload{Header: pHeader, Data: data}
Defensive patterns

Strategy: validation

Validate before calling

func hasHeader(env *cb.Envelope) bool {
    p := &cb.Payload{}
    if env == nil || proto.Unmarshal(env.Payload, p) != nil {
        return false
    }
    return p.Header != nil
}

Type guard

func hasPayloadHeader(p *cb.Payload) bool { return p != nil && p.Header != nil }

Try / catch

req, err := unwrap(raw)
if err != nil {
    if strings.Contains(err.Error(), "no header in payload") {
        return nil, fmt.Errorf("rejecting headerless payload: %w", err)
    }
    return nil, err
}

Prevention

When it happens

Trigger: Submitting an envelope whose Payload was marshaled from a cb.Payload with Header left nil, or an empty payload that decodes to a zero-valued Payload.

Common situations: Hand-built transactions in tests or scripts that forget to attach protoutil.MakePayloadHeader; malformed requests injected via gossip/consensus; tools generating envelopes from templates missing the header.

Related errors


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