hyperledger/fabric · error

failed to create x509 verify options from old and new ordere

Error message

failed to create x509 verify options from old and new orderer config

What it means

This error is returned during config update validation in the etcdraft chain when createX509VerifyOptions fails to build x509 verify options from the new orderer config. It is raised inside validateNewCertExpiration (orderer/consensus/etcdraft/chain.go:1507) as a wrapper (errors.Wrapf) around the underlying cause. Verify options derive TLS CA roots from the orderer config, so malformed config prevents certificate verification of new consenters.

Source

Thrown at orderer/consensus/etcdraft/chain.go:1507

	if oldOrdererConfig.ConsensusMetadata() == nil {
		c.logger.Panic("Programming Error: ValidateConsensusMetadata called with nil old metadata")
		return nil
	}

	oldMetadata := &etcdraft.ConfigMetadata{}
	if err := proto.Unmarshal(oldOrdererConfig.ConsensusMetadata(), oldMetadata); err != nil {
		c.logger.Panicf("Programming Error: Failed to unmarshal old etcdraft consensus metadata: %v", err)
	}

	newMetadata := &etcdraft.ConfigMetadata{}
	if err := proto.Unmarshal(newOrdererConfig.ConsensusMetadata(), newMetadata); err != nil {
		return errors.Wrap(err, "failed to unmarshal new etcdraft metadata configuration")
	}

	verifyOpts, err := createX509VerifyOptions(newOrdererConfig)
	if err != nil {
		return errors.Wrapf(err, "failed to create x509 verify options from old and new orderer config")
	}

	if err := VerifyConfigMetadata(newMetadata, verifyOpts); err != nil {
		return errors.Wrap(err, "invalid new config metadata")
	}

	if newChannel {
		// check if the consenters are a subset of the existing consenters (system channel consenters)
		set := ConsentersToMap(oldMetadata.GetConsenters())
		for _, c := range newMetadata.GetConsenters() {
			if !set.Exists(c) {
				return errors.New("new channel has consenter that is not part of system consenter set")
			}
		}
		return nil
	}

	// create the dummy parameters for ComputeMembershipChanges

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Inspect the wrapped underlying error for the precise cause (e.g. no root CAs found)
  2. Ensure the updated orderer config retains non-empty Orderer.TLS.RootCAs (and ClientRootCAs as needed)
  3. Re-generate and re-upload valid PEM CA certificates to the channel config
  4. Use configtxlator to diff the config update and confirm TLS settings were not accidentally removed

Example fix

// before (config update removing TLS root CAs)
Orderer.TLS.RootCAs: []
// after
Orderer.TLS.RootCAs: [<PEM bytes of org root CA certs>]
Defensive patterns

Strategy: validation

Validate before calling

opts, err := createX509VerifyOptions(newOrdererConfig)
if err != nil {
    // reject / fix config before update: ensure TLS RootCAs present and valid PEM
    log.Fatalf("orderer config TLS unusable: %v", err)
}

Type guard

func hasRootCAs(cfg *orderer.Config) bool {
    return cfg != nil && len(cfg.TLS.RootCAs) > 0
}

Prevention

When it happens

Trigger: A channel config update changes the orderer group while validateNewCertExpiration runs; createX509VerifyOptions fails because the new Orderer config contains no TLS root CAs or yields no valid root certificates.

Common situations: Removing or emptying the TLS CA certificate pool from the orderer config; a config update that drops Orderer.TLS.RootCAs/ClientRootCAs; malformed PEM certificates in the channel config.

Related errors


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