hyperledger/fabric · error
envelope has no header
Error message
envelope has no header
What it means
parseEnvelope in the deliver service (common/deliver/deliver.go) rejects an incoming Envelope whose inner Payload has no Header. Every deliver/Seek request must carry a header (channel + signature headers) so the handler can identify the channel, creator and request timing; without one the envelope cannot be routed or authenticated, so the handler aborts with this error.
Source
Thrown at common/deliver/deliver.go:370
if stopNum == block.Header.Number {
break
}
}
logger.Debugf("[channel: %s] Done delivering to %s for (%p)", chdr.ChannelId, addr, seekInfo)
return cb.Status_SUCCESS, nil
}
func (h *Handler) parseEnvelope(ctx context.Context, envelope *cb.Envelope) (*cb.Payload, *cb.ChannelHeader, *cb.SignatureHeader, error) {
payload, err := protoutil.UnmarshalPayload(envelope.Payload)
if err != nil {
return nil, nil, nil, err
}
if payload.Header == nil {
return nil, nil, nil, errors.New("envelope has no header")
}
chdr, err := protoutil.UnmarshalChannelHeader(payload.Header.ChannelHeader)
if err != nil {
return nil, nil, nil, err
}
shdr, err := protoutil.UnmarshalSignatureHeader(payload.Header.SignatureHeader)
if err != nil {
return nil, nil, nil, err
}
err = h.validateChannelHeader(ctx, chdr)
if err != nil {
return nil, nil, nil, err
}
return payload, chdr, shdr, nilView on GitHub (pinned to 2736b63f8f)
Solutions
- Fix the client so it constructs the payload header via protoutil or SDK helpers, setting channel header (type, timestamp, channel ID) and signature header (creator, nonce).
- Use an existing SDK (fabric-sdk-go/fabric-gateway) rather than hand-marshaling envelopes.
- Inspect the offending envelope (protoutil.EnvelopeToPayload) to confirm the Header is nil and where it was produced.
Example fix
// before
payload := &cb.Payload{Data: data} // Header omitted
env := &cb.Envelope{Payload: protoutil.MarshalOrPanic(payload)}
// after
chdr := &cb.ChannelHeader{Type: int32(cb.HeaderType_DELIVER_SEEK_INFO), ChannelId: chID, TxId: txid}
shdr := &cb.SignatureHeader{Creator: signerSerialised, Nonce: nonce}
env, err := protoutil.CreateEnvelope(protoutil.WithChannelHeader(chdr), protoutil.WithSignatureHeader(shdr), protoutil.WithData(data)) Defensive patterns
Strategy: validation
Validate before calling
payload, err := protoutil.EnvelopeToPayload(envelope)
if err != nil || payload == nil || payload.Header == nil {
return fmt.Errorf("deliver envelope lacks payload header; rebuild with protoutil.CreateEnvelope")
} Type guard
func hasHeader(env *common.Envelope) bool {
p, err := protoutil.UnmarshalPayload(env.Payload)
return err == nil && p != nil && p.Header != nil
} Try / catch
payload, _, _, err := handler.parseEnvelope(ctx, env)
if err != nil {
if strings.Contains(err.Error(), "envelope has no header") {
// rebuild the envelope client-side and resend
}
return err
} Prevention
- Always build envelopes with protoutil.CreateEnvelope or an SDK, never raw struct marshaling
- Unit-test deliver envelope construction to assert Header is set
- Validate envelope shape at client boundaries before sending
When it happens
Trigger: A client submits a deliver (SeekLatestBlock etc.) request whose Envelope.Payload marshals a pb.Payload with Header unset, or an envelope whose payload was hand-crafted/constructed without calling protoutil.WithChannelHeader/SignatureHeader (e.g. building the payload struct manually and forgetting the Header field).
Common situations: Custom CLI tools or test harnesses that build deliver envelopes by hand; a broken/misbehaving SDK producing empty payloads; corrupted or truncated protobuf bytes that still unmarshal but drop the header.
Related errors
- malformed org definition for org: %s
- error encode input
- message of type %s unknown
- error marshaling: proto: Marshal called with nil
- error marshaling
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/251d2bf5c2e1b5c0.
Report an issue: GitHub.