hyperledger/fabric · error

ERROR - only a single deliver source is currently supported

Error message

ERROR - only a single deliver source is currently supported

What it means

InitCmdFactory builds the client factory for peer channel commands. A command can take its block/deliver stream from either the peer's deliver service or the ordering service — never both. Receiving both flags true indicates a developer bug in wiring a new command, so it refuses to proceed.

Source

Thrown at internal/peer/channel/channel.go:136

	GetOldestBlock() (*cb.Block, error)
	GetNewestBlock() (*cb.Block, error)
	Close() error
}

// ChannelCmdFactory holds the clients used by ChannelCmdFactory
type ChannelCmdFactory struct {
	EndorserClient   pb.EndorserClient
	Signer           msp.SigningIdentity
	BroadcastClient  common.BroadcastClient
	DeliverClient    deliverClientIntf
	BroadcastFactory BroadcastClientFactory
}

// InitCmdFactory init the ChannelCmdFactory with clients to endorser and orderer based on the given parameters
func InitCmdFactory(isEndorserRequired, isPeerDeliverRequired, isOrdererRequired bool) (*ChannelCmdFactory, error) {
	if isPeerDeliverRequired && isOrdererRequired {
		// this is likely a bug during development caused by adding a new cmd
		return nil, errors.New("ERROR - only a single deliver source is currently supported")
	}

	var err error
	cf := &ChannelCmdFactory{}

	cf.Signer, err = common.GetDefaultSignerFnc()
	if err != nil {
		return nil, errors.WithMessage(err, "error getting default signer")
	}

	cf.BroadcastFactory = func() (common.BroadcastClient, error) {
		return common.GetBroadcastClientFnc()
	}

	// for join and list, we need the endorser as well
	if isEndorserRequired {
		// creating an EndorserClient with these empty parameters will create a
		// connection using the values of "peer.address" and

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Fix the call site to pass exactly one deliver source: e.g. InitCmdFactory(EndorserRequired, PeerDeliverRequired, OrdererNotRequired) or (..., PeerDeliverNotRequired, OrdererRequired).
  2. Review which service should serve blocks for your command: peer deliver for existing channels, orderer for channel creation.
  3. Write a unit test asserting the flag combination for your command.

Example fix

// before
factory, err := channel.InitCmdFactory(channel.EndorserRequired, channel.PeerDeliverRequired, channel.OrdererRequired)
// after
factory, err := channel.InitCmdFactory(channel.EndorserRequired, channel.PeerDeliverRequired, channel.OrdererNotRequired)
Defensive patterns

Strategy: validation

Validate before calling

// caller-side check when invoking InitCmdFactory
if isPeerDeliverRequired && isOrdererRequired {
    return nil, errors.New("choose exactly one deliver source: peer deliver OR orderer")
}

Try / catch

cf, err := channel.InitCmdFactory(isEndorser, isPeerDeliver, isOrderer)
if err != nil {
    return fmt.Errorf("init channel factory: %w", err)
}

Prevention

When it happens

Trigger: Calling InitCmdFactory with isPeerDeliverRequired=true AND isOrdererRequired=true — typically when adding or modifying a channel subcommand and passing the wrong boolean combination.

Common situations: Contributing a new `peer channel` subcommand; refactoring an existing command's deliver source; copying an InitCmdFactory call and flipping flags incorrectly.

Related errors


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