hyperledger/fabric · error

nil Raft config metadata

Error message

nil Raft config metadata

What it means

VerifyConfigMetadata validates a Raft ConfigMetadata proto. It returns this error when the metadata pointer itself is nil. The comment marks it as defensive: CheckConfigMetadata/metadata construction should never produce a nil ConfigMetadata, so reaching this indicates a programming or decoding failure upstream.

Source

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

	if err != nil {
		return nil, nil, errors.Wrap(err, "failed to extract payload from config envelope")
	}
	// get config update
	configUpdate, err := configtx.UnmarshalConfigUpdateFromPayload(payload)
	if err != nil {
		return nil, nil, errors.Wrap(err, "could not read config update")
	}

	return MetadataFromConfigUpdate(configUpdate)
}

// VerifyConfigMetadata validates Raft config metadata.
// Note: ignores certificates expiration.
func VerifyConfigMetadata(metadata *etcdraft.ConfigMetadata, verifyOpts x509.VerifyOptions) error {
	if metadata == nil {
		// defensive check. this should not happen as CheckConfigMetadata
		// should always be called with non-nil config metadata
		return errors.Errorf("nil Raft config metadata")
	}

	if metadata.GetOptions() == nil {
		return errors.Errorf("nil Raft config metadata options")
	}

	if metadata.GetOptions().GetHeartbeatTick() == 0 ||
		metadata.GetOptions().GetElectionTick() == 0 ||
		metadata.GetOptions().GetMaxInflightBlocks() == 0 {
		// if SnapshotIntervalSize is zero, DefaultSnapshotIntervalSize is used
		return errors.Errorf("none of HeartbeatTick (%d), ElectionTick (%d) and MaxInflightBlocks (%d) can be zero",
			metadata.GetOptions().GetHeartbeatTick(), metadata.GetOptions().GetElectionTick(), metadata.GetOptions().GetMaxInflightBlocks())
	}

	// check Raft options
	if metadata.GetOptions().GetElectionTick() <= metadata.GetOptions().GetHeartbeatTick() {
		return errors.Errorf("ElectionTick (%d) must be greater than HeartbeatTick (%d)",
			metadata.GetOptions().GetElectionTick(), metadata.GetOptions().GetHeartbeatTick())

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Check that the value passed is a non-nil *etcdraft.ConfigMetadata before calling VerifyConfigMetadata.
  2. Confirm the channel config's ConsensusType.Metadata was unmarshalled into etcdraft.ConfigMetadata (not raw bytes).
  3. If metadata comes from a config update, ensure MetadataFromConfigUpdate succeeded without error.

Example fix

// before
err := VerifyConfigMetadata(meta, opts)
// after
if meta == nil { return errors.New("missing raft config metadata") }
err := VerifyConfigMetadata(meta, opts)
Defensive patterns

Strategy: type-guard

Validate before calling

if metadata == nil {
	return errors.New("raft config metadata not extracted; check ConsensusType in channel config")
}

Type guard

func hasRaftMetadata(m *etcdraft.ConfigMetadata) bool { return m != nil }

Try / catch

if err := VerifyConfigMetadata(meta, opts); err != nil {
	if strings.Contains(err.Error(), "nil Raft config metadata") {
		return errors.New("metadata missing entirely - not a raft channel?")
	}
	return err
}

Prevention

When it happens

Trigger: Calling VerifyConfigMetadata(nil, opts) directly, or passing metadata extracted from a config update whose ConsensusType.Metadata failed to decode into etcdraft.ConfigMetadata.

Common situations: Unit tests calling with nil; channel config where consensus_type metadata is empty bytes; unmarshalling skipped but nil result propagated.

Related errors


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