hyperledger/fabric · error

channel header unmarshalling error: %s

Error message

channel header unmarshalling error: %s

What it means

ValidateConfig in orderer/consensus/smartbft/configverifier.go:79 returns "channel header unmarshalling error: %s" when protoutil.UnmarshalChannelHeader fails to decode payload.Header.ChannelHeader bytes into a common.ChannelHeader. The ChannelHeader field is non-nil but its bytes are not a valid protobuf ChannelHeader, so the validator aborts before switching on the envelope type.

Source

Thrown at orderer/consensus/smartbft/configverifier.go:79

// ValidateConfig validates config from envelope
func (cbv *ConfigBlockValidator) ValidateConfig(envelope *common.Envelope) error {
	payload, err := protoutil.UnmarshalPayload(envelope.Payload)
	if err != nil {
		return err
	}

	if payload.Header == nil {
		return fmt.Errorf("no header was set")
	}

	if payload.Header.ChannelHeader == nil {
		return fmt.Errorf("no channel header was set")
	}

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

	switch chdr.Type {
	case int32(common.HeaderType_CONFIG):
		configEnvelope := &common.ConfigEnvelope{}
		if err = proto.Unmarshal(payload.Data, configEnvelope); err != nil {
			return fmt.Errorf("data unmarshalling error: %s", err)
		}
		return cbv.verifyConfigUpdateMsg(envelope, configEnvelope, chdr)
	default:
		return errors.Errorf("unexpected envelope type %s", common.HeaderType_name[chdr.Type])
	}
}

func (cbv *ConfigBlockValidator) checkConsentersMatchPolicy(conf *common.Config) error {
	if conf == nil {
		return fmt.Errorf("empty Config")
	}

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Ensure ChannelHeader is marshaled with proto.Marshal(&common.ChannelHeader{...}) (or protoutil.MarshalOrPanic), not with another message type's bytes.
  2. Verify the block/envelope was not truncated or corrupted; re-fetch from a healthy orderer.
  3. Use protoutil.CreateSignedEnvelope instead of manual payload construction.
  4. Confirm client and orderer use compatible fabric-protos versions (fabric-protos-go vs fabric-protos-go-apiv2 produce identical wire format, but hand-rolled structs may not).

Example fix

// before: wrong message marshaled into the header slot
hdr := &common.Header{ChannelHeader: sighdrBytes} // SignatureHeader bytes
// after
hdr := &common.Header{
    ChannelHeader: protoutil.MarshalOrPanic(&common.ChannelHeader{
        Type: int32(common.HeaderType_CONFIG), ChannelId: "mychannel", Epoch: 0,
    }),
}
Defensive patterns

Strategy: validation

Validate before calling

chdr := &common.ChannelHeader{}
if err := proto.Unmarshal(payload.Header.ChannelHeader, chdr); err != nil {
    return fmt.Errorf("client-side check: channel header bytes are not a valid ChannelHeader: %w", err)
}
if chdr.ChannelId == "" {
    return errors.New("channel header has empty channel id")
}

Type guard

func isWellFormedChannelHeader(b []byte) (*common.ChannelHeader, bool) {
    ch := &common.ChannelHeader{}
    if err := proto.Unmarshal(b, ch); err != nil || ch.ChannelId == "" {
        return nil, false
    }
    return ch, true
}

Try / catch

if err := cbv.ValidateConfig(envelope); err != nil {
    if strings.Contains(err.Error(), "channel header unmarshalling error") {
        return fmt.Errorf("ChannelHeader bytes corrupt: re-marshal a common.ChannelHeader")
    }
    return err
}

Prevention

When it happens

Trigger: An envelope whose Header.ChannelHeader contains bytes that fail proto.Unmarshal as common.ChannelHeader — e.g. random/garbage bytes, bytes from a different message type (SignatureHeader marshaled into the ChannelHeader slot), or truncation.

Common situations: Manual envelope assembly in tests/tools that marshals the wrong message into the ChannelHeader field; corrupted or tampered blocks; double-marshaling bugs in custom clients; version mismatch where a client serializes headers in an incompatible layout.

Understand the failure class

Background: "cannot parse invalid wire-format data", "cannot unmarshal", "failed unmarshalling": protobuf unmarshal errors explained — this error's family across 10 libraries.

Related errors


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