hyperledger/fabric · error

wrong chain type

Error message

wrong chain type

What it means

getPrivateData receives the deliver chain as a generic deliver.Chain interface and immediately asserts it to the local Chain type to access Ledger(). If the injected chain is not this concrete type (a different deliver.Chain implementation), the assertion fails and this error is returned.

Source

Thrown at core/peer/deliverevents.go:182

		Type: &peer.DeliverResponse_BlockAndPrivateData{BlockAndPrivateData: blockAndPvtData},
	}
	return bprs.Send(response)
}

func (bprs *blockAndPrivateDataResponseSender) DataType() string {
	return "block_and_pvtdata"
}

// getPrivateData returns private data for the block
func (bprs *blockAndPrivateDataResponseSender) getPrivateData(
	block *common.Block,
	chain deliver.Chain,
	channelID string,
	signedData *protoutil.SignedData,
) (map[uint64]*rwset.TxPvtReadWriteSet, error) {
	channel, ok := chain.(Chain)
	if !ok {
		return nil, errors.New("wrong chain type")
	}

	pvtData, err := channel.Ledger().GetPvtDataByNum(block.Header.Number, nil)
	if err != nil {
		logger.Errorf("Error getting private data by block number %d on channel %s", block.Header.Number, channelID)
		return nil, errors.Wrapf(err, "error getting private data by block number %d", block.Header.Number)
	}

	seqs2Namespaces := aggregatedCollections(make(map[seqAndDataModel]map[string][]*rwset.CollectionPvtReadWriteSet))

	configHistoryRetriever, err := channel.Ledger().GetConfigHistoryRetriever()
	if err != nil {
		return nil, err
	}

	identityDeserializer, err := bprs.IdentityDeserializerManager.Deserializer(channelID)
	if err != nil {
		return nil, err

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Ensure the chain registered with the deliver handler is the package-local Chain (has Ledger() etc.).
  2. Update mocks in tests to implement the full local Chain interface.
  3. Use embedding (mock embeds the real Chain or implements all methods) so the type assertion succeeds.

Example fix

// before
type fakeChain struct{} // only deliver.Chain methods
handler.getPrivateData(block, fakeChain{}, "mychannel", sd)
// after
type fakeChain struct {
  *peer.Chain // embed to satisfy local Chain interface
}
handler.getPrivateData(block, fakeChain{}, "mychannel", sd)
Defensive patterns

Strategy: type-guard

Validate before calling

if _, ok := chain.(Chain); !ok {
  return errors.New("chain must implement the local Chain interface")
}

Type guard

func asLocalChain(c deliver.Chain) (Chain, bool) {
  ch, ok := c.(Chain)
  return ch, ok
}

Try / catch

pvt, err := getPrivateData(block, chain, chID, sd)
if err != nil && err.Error() == "wrong chain type" {
  return fmt.Errorf("deliver chain is not the local Chain implementation: %w", err)
}

Prevention

When it happens

Trigger: Calling SendBlockResponse (which calls getPrivateData) with a chain value that implements deliver.Chain but not the package-local Chain interface — typically only in tests or when a custom/foreign chain implementation is registered.

Common situations: Unit tests passing mock deliver.Chain implementations that lack the local Chain methods; registering a custom deliver support handler; refactoring that changed the Chain interface without updating all implementations.

Related errors


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