hyperledger/fabric · error

missing channel header

Error message

missing channel header

What it means

The orderer's multichannel registrar, while building ledger resources for a channel from a config transaction envelope, found that the envelope's payload had no header. Fabric envelopes must carry a ChannelHeader identifying the channel and tx type; without it the registrar cannot determine which channel the config belongs to and aborts chain initialization.

Source

Thrown at orderer/common/multichannel/registrar.go:371

	return r.chains[chainID]
}

// GetFollower retrieves the follower.Chain if it exists.
func (r *Registrar) GetFollower(chainID string) *follower.Chain {
	r.lock.RLock()
	defer r.lock.RUnlock()

	return r.followers[chainID]
}

func (r *Registrar) newLedgerResources(configTx *cb.Envelope) (*ledgerResources, error) {
	payload, err := protoutil.UnmarshalPayload(configTx.Payload)
	if err != nil {
		return nil, errors.WithMessage(err, "error umarshaling envelope to payload")
	}

	if payload.Header == nil {
		return nil, errors.New("missing channel header")
	}

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

	configEnvelope, err := configtx.UnmarshalConfigEnvelope(payload.Data)
	if err != nil {
		return nil, errors.WithMessage(err, "error umarshaling config envelope from payload data")
	}

	bundle, err := channelconfig.NewBundle(chdr.ChannelId, configEnvelope.Config, r.bccsp)
	if err != nil {
		return nil, errors.WithMessage(err, "error creating channelconfig bundle")
	}

	err = checkResources(bundle)

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Regenerate the config transaction/genesis block with configtxgen or the configtxlator instead of hand-crafting the envelope
  2. Verify the envelope was built with protoutil.CreateSignedEnvelope so the payload header is populated
  3. Inspect the offending block/ledger data for corruption and rebuild the orderer ledger (wipe data dir and re-join with a valid genesis/join block)
  4. Check client SDK version for known envelope-marshaling bugs and upgrade

Example fix

// before: manual envelope with no header
payload := &common.Payload{Data: configData}
raw, _ := proto.Marshal(payload)

// after: use the helper that sets the header
env, err := protoutil.CreateSignedEnvelope(common.HeaderType_CONFIG, "mychannel", nil, configUpdate, 0, 0)
Defensive patterns

Strategy: validation

Validate before calling

// Go: validate envelope before broadcast/submit
payload, err := protoutil.UnmarshalPayload(env.Payload)
if err != nil { return err }
if payload.Header == nil || len(payload.Header.ChannelHeader) == 0 {
    return errors.New("envelope has no channel header")
}
if _, err := protoutil.UnmarshalChannelHeader(payload.Header.ChannelHeader); err != nil { return err }

Type guard

func hasChannelHeader(p *common.Payload) bool {
    return p != nil && p.Header != nil && len(p.Header.ChannelHeader) > 0
}

Try / catch

if err := validateEnvelope(env); err != nil {
    // don't broadcast; log and resubmit a properly built envelope
    logger.Errorf("skipping malformed envelope: %v", err)
    return err
}

Prevention

When it happens

Trigger: initAppChannels / initLedgerResourcesClusterConsenter / createNewChannel are handed a malformed config envelope whose payload.Header is nil — typically a corrupted or hand-crafted config transaction submitted via Broadcast, or a genesis/join block whose payload did not deserialize with a header.

Common situations: Submitting a manually assembled envelope (marshaled common.Payload without Header set), a truncated/corrupted block file or on-disk ledger entry, or a bug in a client SDK building config update transactions.

Related errors


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