hyperledger/fabric · warning

Claimed seqNum is [ ] but actual seqNum inside block is [ ]

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.

Solutions

  1. Let gossip discard the stale payload (this error is expected handling for out-of-sync blocks)
  2. If persistent, resync the peer: pull latest blocks from the orderer or a healthy peer
  3. 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

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


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

Appendix: 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)