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, errView on GitHub (pinned to 2736b63f8f)
Solutions
- Ensure the chain registered with the deliver handler is the package-local Chain (has Ledger() etc.).
- Update mocks in tests to implement the full local Chain interface.
- 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
- Embed the full local Chain interface in test mocks
- Add var _ Chain = (*mockChain)(nil) compile checks
- Keep the Chain interface small so mocks stay in sync
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
- error getting private data by block number %d
- consenter options type mismatch
- envelope has no header
- channel header in envelope must contain timestamp
- envelope timestamp %s is more than %s apart from current ser
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/d399223be5969a6e.
Report an issue: GitHub.