hyperledger/fabric · error
node id mismatch
Error message
node id mismatch
What it means
VerifyAuthRequest authenticates an incoming cluster Step request. After unwrapping the sender identity (toIdentity), it compares the certificate public key of that identity against the local node's configured identity (s.NodeIdentity). If CompareCertPublicKeys reports the keys are not equal, the request claims to come from a node other than the one this peer expects for that channel, so the RPC is rejected with 'node id mismatch'.
Source
Thrown at orderer/common/cluster/clusterservice.go:172
}
fromIdentity := membership.MemberMapping[authReq.FromId]
if fromIdentity == nil {
return nil, errors.Errorf("node %d is not member of channel %s", authReq.FromId, authReq.Channel)
}
toIdentity := membership.MemberMapping[authReq.ToId]
if toIdentity == nil {
return nil, errors.Errorf("node %d is not member of channel %s", authReq.ToId, authReq.Channel)
}
equal, err := CompareCertPublicKeys(toIdentity, s.NodeIdentity)
if err != nil {
return nil, errors.Wrap(err, "failed to compare cert public keys")
}
if !equal {
s.Logger.Debugf("node id mismatch for node %d, toIdentity: %s, s.NodeIdentity: %s", authReq.FromId, string(toIdentity), string(s.NodeIdentity))
return nil, errors.Errorf("node id mismatch")
}
err = VerifySignature(fromIdentity, SHA256Digest(msg), authReq.Signature)
if err != nil {
return nil, errors.Wrap(err, "signature mismatch")
}
return authReq, nil
}
func (s *ClusterService) handleMessage(stream ClusterStepStream, addr string, exp *certificateExpirationCheck, channel string, sender uint64, streamID uint64) error {
request, err := stream.Recv()
if err == io.EOF {
return err
}
if err != nil {
s.Logger.Warningf("Stream read from %s failed: %v", addr, err)
return errView on GitHub (pinned to 2736b63f8f)
Solutions
- Regenerate/redeploy the orderer with the correct TLS certificate matching the identity registered in the channel configuration (crypto-material consistency across all orderers).
- Compare the log line's toIdentity vs s.NodeIdentity (Debug level) and replace whichever side is stale — usually update the channel config's orderer TLS certs via a config update transaction.
- Verify orderer.yaml General.TLS.Certificate and General.Cluster.* certificate paths point to the same cert generation as the channel's crypto material.
- Ensure all orderers use certs issued by the same TLS CA recorded in the channel config; re-run the network bootstrap or perform an ordering-service config update if CAs changed.
- Check for clock/genesis-block mismatch: confirm every node joined the same channel with the same genesis block so membership expectations align.
Example fix
// before (orderer.yaml, node re-deployed with new certs but channel still expects old)
General:
TLS:
Certificate: /crypto/tls/new-server.crt
// after — redeploy with the cert generation recorded in channel config, or update channel config:
// configtxlator/ledger update: Orderer -> OrdererEndpoints + TLS certs => new-server.crt registered for this node Defensive patterns
Strategy: validation
Validate before calling
// Before deploying/starting the orderer, verify the node identity matches the TLS cert
localCert := loadTLSCert("/crypto/tls/server.crt")
if !publicKeyEqual(localCert.PublicKey, nodeIdentityCert.PublicKey) {
return fmt.Errorf("TLS cert does not match configured NodeIdentity for this orderer")
} Type guard
func identityMatches(tlsCert, nodeIdentity *x509.Certificate) bool {
if tlsCert == nil || nodeIdentity == nil { return false }
equal, err := CompareCertPublicKeys(tlsCert.Raw, nodeIdentity.Raw)
return err == nil && equal
} Prevention
- Deploy all orderers from a single, consistent crypto-material generation
- After any TLS cert rotation, perform a channel config update so every node's registered identity matches its new cert
- Watch orderer logs for 'node id mismatch' at debug level during rollout and stop if they appear
- Verify cert fingerprints across nodes before joining an orderer to a channel
When it happens
Trigger: ClusterService.Step receives an authReq whose FromId declares a sender, but the cert public key in the TLS/client context differs from s.NodeIdentity (the identity registered for the local node in the cluster RPC). This happens when the remote orderer presents the wrong TLS or client cert, or when the local node's TLS cert/identity was rotated or misconfigured so the configured NodeIdentity no longer matches what the peer actually authenticates with.
Common situations: A channel was formed on one set of orderer certs but an orderer was re-deployed with regenerated TLS certificates while the channel genesis/config still carries the old certs; crypto material copied between nodes so two orderers share/expect mismatched identities; org admin updated MSP or TLS CA but didn't update all orderers; typo in General.Cluster.ClientCertificate/ServerCertificate or in the channel's orderer endpoint/identity config.
Related errors
- Chaincode %s with given certificate hash %v belongs to a dif
- got unexpected status: %v -- %s
- channel %s doesn't exist
- previous block header is nil
- sequences %d and %d were received consecutively
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/9eb3e0594aa03cfb.
Report an issue: GitHub.