hyperledger/fabric · error

failed to extract envelope from the block

Error message

failed to extract envelope from the block

What it means

ConfigChannelHeader extracts envelope 0 from what must be a config block and returns its channel header type. If protoutil.ExtractEnvelope fails — the block is nil/has no data, index 0 does not exist, or the payload is malformed — the error is wrapped as 'failed to extract envelope from the block'. It signals the caller (writeConfigBlock) was handed something that is not a valid config block.

Source

Thrown at orderer/consensus/etcdraft/util.go:138

			if val, ok := ordererConfigGroup.GetValues()["ConsensusType"]; ok {
				if baseVersion == val.GetVersion() {
					// Only if the version in the write set differs from the read-set
					// should we consider this to be an update to the consensus type
					return nil, nil, nil
				}
				return MetadataFromConfigValue(val)
			}
		}
	}
	return nil, nil, nil
}

// ConfigChannelHeader expects a config block and returns the header type
// of the config envelope wrapped in it, e.g. HeaderType_ORDERER_TRANSACTION
func ConfigChannelHeader(block *common.Block) (hdr *common.ChannelHeader, err error) {
	envelope, err := protoutil.ExtractEnvelope(block, 0)
	if err != nil {
		return nil, errors.Wrap(err, "failed to extract envelope from the block")
	}

	channelHeader, err := protoutil.ChannelHeader(envelope)
	if err != nil {
		return nil, errors.Wrap(err, "cannot extract channel header")
	}

	return channelHeader, nil
}

// ConfigEnvelopeFromBlock extracts configuration envelope from the block based on the
// config type, i.e. HeaderType_ORDERER_TRANSACTION or HeaderType_CONFIG
func ConfigEnvelopeFromBlock(block *common.Block) (*common.Envelope, error) {
	if block == nil {
		return nil, errors.New("nil block")
	}

	envelope, err := protoutil.ExtractEnvelope(block, 0)

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Verify the block passed to writeConfigBlock is a genuine, fully formed config block (non-nil Data with at least one envelope)
  2. Check for block corruption on disk; if the genesis block is bad, recreate/rejoin the channel
  3. Trace the block source (file ledger / replication) for truncation and restore from a valid peer/orderer copy

Example fix

// before
hdr, err := ConfigChannelHeader(block)
// after
if block == nil || block.Data == nil || len(block.Data.Data) == 0 {
	return errors.New("invalid config block: no envelopes")
}
hdr, err := ConfigChannelHeader(block)
Defensive patterns

Strategy: type-guard

Validate before calling

func isWellFormedConfigBlock(block *common.Block) bool {
	return block != nil && block.Header != nil && block.Data != nil &&
		len(block.Data.Data) > 0
}
// use before passing to writeConfigBlock

Type guard

func hasEnvelopeAtIndex(block *common.Block, i uint64) bool {
	if block == nil || block.Data == nil {
		return false
	}
	envs, err := protoutil.GetEnvelopeFromBlock(block.Data.Data) 
	_ = envs
	return err == nil && len(block.Data.Data) > int(i)
}

Try / catch

hdr, err := ConfigChannelHeader(block)
if err != nil {
	if strings.Contains(err.Error(), "failed to extract envelope from the block") {
		return fmt.Errorf("block %d is not a valid config block — check ledger/replication source", block.GetHeader().GetNumber())
	}
	return err
}

Prevention

When it happens

Trigger: writeConfigBlock invokes ConfigChannelHeader on a block whose Data is empty or whose first envelope fails extraction/validation (bad signature header framing, truncated payload bytes).

Common situations: A zero or malformed block passed into the raft consensus layer during chain init; block corruption on disk; a caller mistakenly passing a regular (non-config) or partially formed block.

Related errors


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