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

  1. Inspect the new config block: ensure it has a valid Orderer group with consenter definitions and valid TLS/identity certs
  2. Re-run the channel config update with correctly generated consenter entries (correct MSP IDs, certs, ports)
  3. Verify the block's last-config index points at a real orderer config block
  4. 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

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


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