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, nil

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. 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).
  2. Use an existing SDK (fabric-sdk-go/fabric-gateway) rather than hand-marshaling envelopes.
  3. 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

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


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