hyperledger/fabric · error
last config is nil
Error message
last config is nil
What it means
SmartBFT blocks carry OrdererBlockMetadata inside the block's orderer metadata, including a LastConfig index pointing at the block number of the most recent config block. verifyBlockDataAndMetadata computes the expected last-config index (persisted or, for config blocks, the block's own number) and first checks that the signed metadata actually contains a LastConfig. This error means the OrdererBlockMetadata signature metadata has a nil LastConfig field, so the verifier cannot validate the block's config lineage.
Source
Thrown at orderer/consensus/smartbft/verifier.go:311
if !proto.Equal(metadataInBlock, metadataFromProposal) {
return nil, errors.Errorf(
"expected metadata in block to be [view_id:%d latest_sequence:%d] but got [view_id:%d latest_sequence:%d]",
metadataFromProposal.GetViewId(), metadataFromProposal.GetLatestSequence(),
metadataInBlock.GetViewId(), metadataInBlock.GetLatestSequence(),
)
}
rtc := v.RuntimeConfig.Load().(RuntimeConfig)
lastConfig := rtc.LastConfigBlock.Header.Number
if protoutil.IsConfigBlock(block) {
lastConfig = block.Header.Number
}
// Verify last config
if ordererMetadataFromSignature.LastConfig == nil {
return nil, errors.Errorf("last config is nil")
}
if ordererMetadataFromSignature.LastConfig.Index != lastConfig {
return nil, errors.Errorf("last config in block orderer metadata points to %d but our persisted last config is %d", ordererMetadataFromSignature.LastConfig.Index, lastConfig)
}
rawLastConfig, err := protoutil.GetMetadataFromBlock(block, cb.BlockMetadataIndex_LAST_CONFIG)
if err != nil {
return nil, err
}
lastConf := &cb.LastConfig{}
if err := proto.Unmarshal(rawLastConfig.Value, lastConf); err != nil {
return nil, err
}
if lastConf.Index != lastConfig {
return nil, errors.Errorf("last config in block metadata points to %d but our persisted last config is %d", ordererMetadataFromSignature.LastConfig.Index, lastConfig)
}
View on GitHub (pinned to 2736b63f8f)
Solutions
- Verify all ordering nodes run a Fabric version that populates OrdererBlockMetadata.LastConfig and upgrade any outdated nodes.
- Force a view change / re-proposal so a healthy leader rebuilds the block with complete orderer metadata.
- Inspect the offending block's metadata for corruption; restore the ledger from a snapshot if bytes are malformed.
- If this occurs during channel creation or genesis processing, regenerate the genesis block with the standard configtxgen tooling instead of custom-built blocks.
Example fix
// before: block built without last-config field
OrdererBlockMetadata{ConsenterMetadata: md} // LastConfig nil -> error
// after: proposer always sets it
OrdererBlockMetadata{ConsenterMetadata: md, LastConfig: &cb.LastConfig{Index: lastConfigBlockNumber}} Defensive patterns
Strategy: validation
Validate before calling
omd := &common.OrdererBlockMetadata{}
if err := proto.Unmarshal(ordererMDBytes, omd); err != nil { return err }
if omd.GetLastConfig() == nil {
return errors.New("OrdererBlockMetadata missing LastConfig")
} Try / catch
if err := verifyProposal(prop); err != nil {
if strings.Contains(err.Error(), "last config is nil") {
// drop proposal, request re-proposal / view change
}
return err
} Prevention
- Never hand-craft blocks; use standard Fabric block-building code paths
- Keep orderer versions homogeneous across the consenter set
- Validate block metadata completeness after any crash-recovery
When it happens
Trigger: VerifyProposal -> verifyBlockDataAndMetadata: for a block being verified, ordererMetadataFromSignature.LastConfig is nil (the proto field was never populated by the proposer), regardless of whether the block is a config or normal block.
Common situations: A proposer built the block with an older/different code path that omits LastConfig; corrupted block metadata bytes; a hand-crafted or replayed proposal from a non-standard tool; mixed Fabric versions where the LastConfig field is not set.
Related errors
- failed unmarshalling OrdererBlockMetadata
- expected metadata in block to be [view_id:%d latest_sequence
- last config in block orderer metadata points to %d but our p
- last config in block metadata points to %d but our persisted
- block metadata is of size %d but should be of size %d
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/a3abca3763578ab2.
Report an issue: GitHub.