hyperledger/fabric · error

unknown orderer type: %s

Error message

unknown orderer type: %s

What it means

NewOrdererGroup only recognizes solo, etcdraft, and BFT consensus types (the ConsensusType* constants). Any other conf.OrdererType string falls through to the default branch and fails with this error. It is a fail-fast guard against typo'd or unsupported orderer types in the channel configuration.

Source

Thrown at internal/configtxgen/encoder/encoder.go:232

	case ConsensusTypeEtcdRaft:
		if consensusMetadata, err = channelconfig.MarshalEtcdRaftMetadata(conf.EtcdRaft); err != nil {
			return nil, errors.Errorf("cannot marshal metadata for orderer type %s: %s", ConsensusTypeEtcdRaft, err)
		}
	case ConsensusTypeBFT:
		consenterProtos, err := consenterProtosFromConfig(conf.ConsenterMapping)
		if err != nil {
			return nil, errors.Errorf("cannot load consenter config for orderer type %s: %s", ConsensusTypeBFT, err)
		}
		addValue(ordererGroup, channelconfig.OrderersValue(consenterProtos), channelconfig.AdminsPolicyKey)
		if consensusMetadata, err = channelconfig.MarshalBFTOptions(conf.SmartBFT); err != nil {
			return nil, errors.Errorf("consenter options read failed with error %s for orderer type %s", err, ConsensusTypeBFT)
		}
		// Force leader rotation to be turned off
		conf.SmartBFT.LeaderRotation = smartbft.Options_ROTATION_OFF
		// Overwrite policy manually by computing it from the consenters
		policies.EncodeBFTBlockVerificationPolicy(consenterProtos, ordererGroup)
	default:
		return nil, errors.Errorf("unknown orderer type: %s", conf.OrdererType)
	}

	addValue(ordererGroup, channelconfig.ConsensusTypeValue(conf.OrdererType, consensusMetadata), channelconfig.AdminsPolicyKey)

	for _, org := range conf.Organizations {
		var err error
		ordererGroup.Groups[org.Name], err = NewOrdererOrgGroup(org, channelCapabilities)
		if err != nil {
			return nil, errors.Wrap(err, "failed to create orderer org")
		}
	}

	ordererGroup.ModPolicy = channelconfig.AdminsPolicyKey
	return ordererGroup, nil
}

func consenterProtosFromConfig(consenterMapping []*genesisconfig.Consenter) ([]*cb.Consenter, error) {
	var consenterProtos []*cb.Consenter

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Set Orderer.OrdererType exactly to one of: solo, etcdraft, or BFT (case-sensitive)
  2. Replace removed 'kafka' orderer type with etcdraft or BFT
  3. Check capitalization: BFT is uppercase; use 'etcdraft' all lowercase
  4. Regenerate the config after correcting the value

Example fix

# before
Orderer:
    OrdererType: kafka
# after
Orderer:
    OrdererType: etcdraft
Defensive patterns

Strategy: validation

Validate before calling

var validOrdererTypes = map[string]bool{"solo": true, "etcdraft": true, "BFT": true}
func validateOrdererType(conf *genesisconfig.Orderer) error {
    if !validOrdererTypes[conf.OrdererType] {
        return fmt.Errorf("OrdererType %q invalid; must be solo, etcdraft, or BFT", conf.OrdererType)
    }
    return nil
}

Type guard

func isKnownOrdererType(t string) bool { return t == "solo" || t == "etcdraft" || t == "BFT" }

Try / catch

group, err := encoder.NewOrdererGroup(conf, caps)
if err != nil && strings.Contains(err.Error(), "unknown orderer type") {
    return fmt.Errorf("OrdererType must be exactly one of solo/etcdraft/BFT: %w", err)
}

Prevention

When it happens

Trigger: NewOrdererGroup/NewChannelGroup invoked with genesisconfig.Orderer.OrdererType set to anything other than "solo", "etcdraft", or "BFT" — e.g. "kafka", "raft", "smartbft", or a case mismatch.

Common situations: Migrating old Fabric 1.x kafka profiles (kafka was removed), typos like 'etcdRaft' vs 'etcdraft', or writing 'SmartBFT' instead of the constant 'BFT'.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


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