hyperledger/fabric · error

consenter %s:%d has invalid certificates

Error message

consenter %s:%d has invalid certificates

What it means

When a config update adds consenter nodes, each newly added node's TLS certificates are validated for expiration and trust against the verify options (orderer/consensus/etcdraft/chain.go:1539). This error wraps the validation failure (e.g. expired certificate or untrusted chain) for a specific host:port. The config update is rejected so a bad node never joins the raft cluster.

Source

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

		}
		return nil
	}

	// create the dummy parameters for ComputeMembershipChanges
	c.raftMetadataLock.RLock()
	dummyOldBlockMetadata := proto.Clone(c.opts.BlockMetadata).(*etcdraft.BlockMetadata)
	c.raftMetadataLock.RUnlock()

	dummyOldConsentersMap := CreateConsentersMap(dummyOldBlockMetadata, oldMetadata)
	changes, err := ComputeMembershipChanges(dummyOldBlockMetadata, dummyOldConsentersMap, newMetadata.GetConsenters())
	if err != nil {
		return err
	}

	// new config metadata was verified above. Additionally need to check new consenters for certificates expiration
	for _, c := range changes.AddedNodes {
		if err := validateConsenterTLSCerts(c, verifyOpts, false); err != nil {
			return errors.Wrapf(err, "consenter %s:%d has invalid certificates", c.GetHost(), c.GetPort())
		}
	}

	active := c.ActiveNodes.Load().([]uint64)
	if changes.UnacceptableQuorumLoss(active) {
		c.logger.Debugf("%d out of %d nodes are alive - %+v", len(active), len(dummyOldConsentersMap), active)
		return errors.Errorf("%d out of %d nodes are alive, configuration will result in quorum loss", len(active), len(dummyOldConsentersMap))
	}

	return nil
}

// StatusReport returns the ConsensusRelation & Status
func (c *Chain) StatusReport() (types.ConsensusRelation, types.Status) {
	c.statusReportMutex.Lock()
	defer c.statusReportMutex.Unlock()

	return c.consensusRelation, c.status

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Read the wrapped cause and re-issue fresh TLS certs for the named consenter
  2. Sign the new node's certs with a CA present in Orderer.TLS.RootCAs
  3. Update the channel config with the renewed certs and resubmit the update
  4. Synchronize the new node's system clock before generating certs

Example fix

// before
fabric-ca-client enroll -u https://admin:pw@ca:7054 --tls.certfiles old-ca.pem // cert from unconfigured/expired CA
// after
fabric-ca-client enroll -u https://admin:pw@ca:7054 --tls.certfiles config-rootca.pem // cert chaining to Orderer.TLS.RootCAs
Defensive patterns

Strategy: validation

Validate before calling

for _, c := range changes.AddedNodes {
    if err := validateConsenterTLSCerts(c, verifyOpts, false); err != nil {
        return fmt.Errorf("pre-check failed for %s:%d: %w", c.GetHost(), c.GetPort(), err)
    }
}

Type guard

func certsFresh(c *common.Consenter, now time.Time) bool {
    cert, err := parseCert(c.GetServerTlsCert())
    return err == nil && now.After(cert.NotBefore) && now.Before(cert.NotAfter)
}

Try / catch

if err := submitConfigUpdate(cfg); err != nil {
    if strings.Contains(err.Error(), "has invalid certificates") {
        // re-enroll the named consenter with a CA in RootCAs and resubmit
    }
}

Prevention

When it happens

Trigger: A config update that adds a consenter whose TLS server or client certificate fails validateConsenterTLSCerts — expired cert, cert not yet valid, or no chain to a root CA in the verify options.

Common situations: Enrolling new orderer nodes with certificates that are already expired or issued by a non-configured CA; long-lived environments where node certs lapsed before joining; generating certs with a clock-skewed machine.

Understand the failure class

Related errors


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