hyperledger/fabric · error

consenter options type mismatch

Error message

consenter options type mismatch

What it means

MarshalBFTOptions clones the smartbft.Options via proto.Clone and type-asserts the result back to *smartbft.Options; the assertion failing yields this error. With correct proto types the assertion always succeeds, so this indicates op is nil or not actually a *smartbft.Options (wrong concrete type or unregistered proto type). Thrown from the public MarshalBFTOptions, called by NewOrdererGroup.

Source

Thrown at common/channelconfig/util.go:337

			return nil, fmt.Errorf("cannot load client cert for consenter %s:%d: %s", c.GetHost(), c.GetPort(), err)
		}
		c.ClientTlsCert = clientCert

		serverCert, err := os.ReadFile(string(c.GetServerTlsCert()))
		if err != nil {
			return nil, fmt.Errorf("cannot load server cert for consenter %s:%d: %s", c.GetHost(), c.GetPort(), err)
		}
		c.ServerTlsCert = serverCert
	}
	return proto.Marshal(copyMd)
}

// MarshalBFTOptions serializes smartbft options.
func MarshalBFTOptions(op *smartbft.Options) ([]byte, error) {
	if copyMd, ok := proto.Clone(op).(*smartbft.Options); ok {
		return proto.Marshal(copyMd)
	} else {
		return nil, errors.New("consenter options type mismatch")
	}
}

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Ensure a non-nil *smartbft.Options with the current fabric-protos smartbft types is passed to NewOrdererGroup / MarshalBFTOptions.
  2. Rebuild with a single consistent version of github.com/hyperledger/fabric-protos-go so there is no vendored duplicate smartbft package.
  3. Check the orderer config selection code path: BFT consensus must populate OrdererConfig with smartbft.Options, not etcdraft or another type's options.
  4. If marshaling manually, verify via reflection that op is *smartbft.Options before calling.

Example fix

// before
var op *smartbft.Options // nil
bytes, err := MarshalBFTOptions(op)
// after
op := &smartbft.Options{N: 1, ...}
bytes, err := MarshalBFTOptions(op)
Defensive patterns

Strategy: type-guard

Validate before calling

func validBFTOptions(op *smartbft.Options) bool {
	return op != nil
}
if !validBFTOptions(op) {
	return errors.New("smartbft options must be non-nil")
}

Type guard

func isSmartBFTOptions(m proto.Message) (*smartbft.Options, bool) {
	op, ok := m.(*smartbft.Options)
	if !ok || op == nil {
		return nil, false
	}
	return op, true
}

Try / catch

// errors are returned, not panicked
bytes, err := channelconfig.MarshalBFTOptions(op)
if err != nil {
	return fmt.Errorf("marshal smartbft options: %w", err)
}

Prevention

When it happens

Trigger: NewOrdererGroup with BFT orderer type where the options passed as *smartbft.Options are nil or are actually a different proto message type, so proto.Clone returns a clone that fails the *smartbft.Options assertion.

Common situations: Mixing smartbft versions/types where the compiled proto type differs from the one asserted; passing nil Options into orderer group creation; custom builds with renamed or vendored smartbft packages producing two distinct Go types.

Related errors


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