hyperledger/fabric · critical
remote nodes cannot be computed, rejecting config block
Error message
remote nodes cannot be computed, rejecting config block
What it means
When a config block is committed, RuntimeConfig.configBlockCommitted recomputes the consenter set via remoteNodesFromConfigBlock. If that fails (e.g. the block cannot be parsed, is not an orderer config block, consenter identities/certs are invalid, or MSP/crypto material can't be processed), the block commit is rejected with this wrapped error to avoid proceeding with an unknown remote-node set.
Source
Thrown at orderer/consensus/smartbft/util.go:77
}
return RuntimeConfig{
consenters: rtc.consenters,
BFTConfig: rtc.BFTConfig,
id: rtc.id,
logger: rtc.logger,
LastCommittedBlockHash: hex.EncodeToString(protoutil.BlockHeaderHash(block.Header)),
Nodes: rtc.Nodes,
ID2Identities: rtc.ID2Identities,
RemoteNodes: rtc.RemoteNodes,
LastBlock: block,
LastConfigBlock: rtc.LastConfigBlock,
}, nil
}
func (rtc RuntimeConfig) configBlockCommitted(block *cb.Block, bccsp bccsp.BCCSP) (RuntimeConfig, error) {
nodeConf, err := remoteNodesFromConfigBlock(block, rtc.logger, bccsp)
if err != nil {
return rtc, errors.Wrap(err, "remote nodes cannot be computed, rejecting config block")
}
bftConfig, err := configBlockToBFTConfig(rtc.id, block, bccsp)
if err != nil {
return RuntimeConfig{}, err
}
return RuntimeConfig{
consenters: nodeConf.consenters,
BFTConfig: bftConfig,
isConfig: true,
id: rtc.id,
logger: rtc.logger,
LastCommittedBlockHash: hex.EncodeToString(protoutil.BlockHeaderHash(block.Header)),
Nodes: nodeConf.nodeIDs,
ID2Identities: nodeConf.id2Identities,
RemoteNodes: nodeConf.remoteNodes,
LastBlock: block,View on GitHub (pinned to 2736b63f8f)
Solutions
- Inspect the new config block: ensure it has a valid Orderer group with consenter definitions and valid TLS/identity certs
- Re-run the channel config update with correctly generated consenter entries (correct MSP IDs, certs, ports)
- Verify the block's last-config index points at a real orderer config block
- Check orderer logs for the inner wrapped error from remoteNodesFromConfigBlock to pinpoint the bad entry
Defensive patterns
Strategy: validation
Validate before calling
// before committing, decode the proposed config block
env, _ := protoutil.UnmarshalEnvelope(block.Data.Data[0])
payload, _ := protoutil.UnmarshalPayload(env.Payload)
cfgEnv, _ := configtx.UnmarshalConfigEnvelope(payload.Data)
if cfgEnv.Config.ChannelGroups["Orderer"] == nil || len(cfgEnv.Config.ChannelGroups["Orderer"].Groups["Consortiums"]) > 0 && cfgEnv.Config.ChannelGroups["Orderer"].Values["Orderers"] == nil {
return errors.New("proposed config has no valid orderer/consenter section")
} Try / catch
if err := chain.BlockCommitted(block); err != nil && strings.Contains(err.Error(), "remote nodes cannot be computed") {
logger.Panicf("config block unusable, halt orderer for manual recovery: %v", err)
} Prevention
- Always round-trip proposed channel config through configtxlator and verify consenter entries
- Keep consenter TLS/identity certs and MSP IDs valid when updating endpoints
- Never delete the Orderer group in channel updates
- Back up the last good config block before applying updates
When it happens
Trigger: BlockCommitted callback after a channel configuration transaction where the new config block lacks a valid orderer group or contains malformed consenter entries/TLS certs that remoteNodesFromConfigBlock cannot decode.
Common situations: Channel update that removed the orderer config section, consenter endpoints or certificates corrupted during configtxlator edits, or a non-config block passed as the latest config block due to LastConfig index issues.
Related errors
- empty block
- identity isn't an MSP Identity
- failed unmarshalling envelope of config block
- failed getting a new bundle from envelope of config block
- failed obtaining MSPs from MSPManager
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/c16d60333a590473.
Report an issue: GitHub.