hyperledger/fabric · warning
Claimed seqNum is [%d] but actual seqNum inside block is [%d
Error message
Claimed seqNum is [%d] but actual seqNum inside block is [%d]
What it means
VerifyBlock confirms that the sequence number claimed by the gossip message matches the actual block number inside the block header. If seqNum != block.Header.Number the block does not correspond to the message, so validation fails with both numbers in the message.
Source
Thrown at internal/peer/gossip/mcs.go:135
if err != nil {
mcsLogger.Errorf("Failed computing digest of serialized identity %s: [%s]", peerIdentity, err)
return nil
}
return digest
}
// VerifyBlock returns nil if the block is properly signed, and the claimed seqNum is the
// sequence number that the block's header contains.
// else returns error
func (s *MSPMessageCryptoService) VerifyBlock(chainID common.ChannelID, seqNum uint64, block *pcommon.Block) error {
if block.Header == nil {
return fmt.Errorf("Invalid Block on channel [%s]. Header must be different from nil.", chainID)
}
blockSeqNum := block.Header.Number
if seqNum != blockSeqNum {
return fmt.Errorf("Claimed seqNum is [%d] but actual seqNum inside block is [%d]", seqNum, blockSeqNum)
}
// - Extract channelID and compare with chainID
channelID, err := protoutil.GetChannelIDFromBlock(block)
if err != nil {
return fmt.Errorf("Failed getting channel id from block with id [%d] on channel [%s]: [%s]", block.Header.Number, chainID, err)
}
if channelID != string(chainID) {
return fmt.Errorf("Invalid block's channel id. Expected [%s]. Given [%s]", chainID, channelID)
}
// - Unmarshal medatada
if block.Metadata == nil || len(block.Metadata.Metadata) == 0 {
return fmt.Errorf("Block with id [%d] on channel [%s] does not have metadata. Block not valid.", block.Header.Number, chainID)
}
dataHash, err := protoutil.BlockDataHash(block.Data)View on GitHub (pinned to 2736b63f8f)
Solutions
- Let gossip discard the stale payload (this error is expected handling for out-of-sync blocks)
- If persistent, resync the peer: pull latest blocks from the orderer or a healthy peer
- Check for ordering/kafka-raft misconfiguration if many peers report mismatches
Defensive patterns
Strategy: retry
Validate before calling
func seqMatches(b *pcommon.Block, claimed uint64) bool {
return b != nil && b.Header != nil && b.Header.Number == claimed
} Type guard
func seqMatches(b *pcommon.Block, claimed uint64) bool {
return b != nil && b.Header != nil && b.Header.Number == claimed
}
if !seqMatches(block, seqNum) {
// skip stale payload; gossip will deliver a fresh one
return nil
} Try / catch
if err := cryptoService.VerifyBlock(chainID, seqNum, block); err != nil {
if strings.Contains(err.Error(), "Claimed seqNum") {
log.Debugf("stale/seq-mismatched block, ignoring: %v", err)
return nil
}
return err
} Prevention
- Treat seq mismatch as normal gossip churn — do not crash the service
- Monitor how often mismatches occur; frequent ones indicate syncing problems
- Re-pull blocks from the orderer after long partitions
When it happens
Trigger: Gossip delivery/state-transfer passes a block whose Header.Number differs from the seqNum the peer claims — e.g. stale message replayed after ledger advanced, or mis-indexed block in a pull.
Common situations: Network partitions causing stale gossip payloads; replayed anti-entropy messages; a bug in block puller assigning wrong sequence numbers after a checkpoint/resync.
Related errors
- failed unmarshalling alive message
- failed unmarshalling stateInfo message
- wasn't able to read ledger height
- was not able to retrieve private data from transient store,
- Invalid Block on channel [%s]. Header must be different from
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/571e1bed0c039f23.
Report an issue: GitHub.