{"record":{"id":"7e47f6fd48181ba3","repo":"hyperledger/fabric","slug":"node-d-doesn-t-exist-in-channel-s-s-membership-7e47f6","errorCode":null,"errorMessage":"node %d doesn't exist in channel %s's membership","messagePattern":"node (.+?) doesn't exist in channel (.+?)'s membership","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"orderer/common/cluster/commauth.go","lineNumber":57,"sourceCode":"\tNodeIdentity   []byte\n\tSigner         identity.Signer\n}\n\nfunc (ac *AuthCommMgr) Remote(channel string, id uint64) (*RemoteContext, error) {\n\tac.Lock.RLock()\n\tdefer ac.Lock.RUnlock()\n\n\tif ac.shutdown {\n\t\treturn nil, errors.New(\"communication has been shut down\")\n\t}\n\n\tmapping, exists := ac.Chan2Members[channel]\n\tif !exists {\n\t\treturn nil, errors.Errorf(\"channel %s doesn't exist\", channel)\n\t}\n\tstub := mapping.ByID(id)\n\tif stub == nil {\n\t\treturn nil, errors.Errorf(\"node %d doesn't exist in channel %s's membership\", id, channel)\n\t}\n\n\tif stub.Active() {\n\t\treturn stub.RemoteContext, nil\n\t}\n\n\terr := stub.Activate(ac.createRemoteContext(stub, channel))\n\tif err != nil {\n\t\treturn nil, errors.WithStack(err)\n\t}\n\treturn stub.RemoteContext, nil\n}\n\nfunc (ac *AuthCommMgr) Configure(channel string, members []RemoteNode) {\n\tac.Logger.Infof(\"Configuring communication module for Channel: %s with nodes:%v\", channel, members)\n\n\tac.Lock.Lock()\n\tdefer ac.Lock.Unlock()","sourceCodeStart":39,"sourceCodeEnd":75,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/orderer/common/cluster/commauth.go#L39-L75","documentation":"AuthCommMgr.Remote() found the channel's membership mapping but the requested node ID has no stub in it (mapping.ByID(id) returned nil). This means the node with that consenter ID is not part of the channel's current membership as known to this orderer.","triggerScenarios":"Calling Remote(channel, id) where id is not in the RemoteNode set last passed to Configure(channel, members) for that channel - e.g. an ID that was removed in a config update, a never-existing consenter ID, or a stale ID cached by the caller (e.g. etcdraft tracking) after a membership change.","commonSituations":"Channel configuration reconfiguration removed/renumbered consenters while a caller still references the old node ID; hardcoded or mis-derived node IDs in custom chaincode/consenter code; TLS/endpoint changes that recreate stubs under different IDs; calling Remote against a channel whose consenter set excludes this cluster node.","solutions":["Verify the node ID is a valid consenter in the channel's current config (check the orderer's channel config / configtx consenter list).","Re-run Configure(channel, members) with the current channel membership so removed/new consenters are reflected.","After any channel reconfiguration, invalidate any cached node IDs and re-resolve membership before calling Remote.","Check the channel name again - a wrong channel can exist but contain a different consenter set, producing this error instead of 'channel doesn't exist'."],"exampleFix":"// before\nrc, err := comm.Remote(\"mychannel\", 7) // node 7 removed in latest config\n// after\ncomm.Configure(\"mychannel\", currentChannelMembers) // refresh membership\nif mapping.ByID(7) != nil { rc, err = comm.Remote(\"mychannel\", 7) }","handlingStrategy":"validation","validationCode":"func nodeInChannel(mgr *cluster.AuthCommMgr, channel string, id uint64) bool {\n    mgr.Lock.RLock()\n    defer mgr.Lock.RUnlock()\n    mapping, ok := mgr.Chan2Members[channel]\n    if !ok { return false }\n    return mapping.ByID(id) != nil\n}\nif !nodeInChannel(mgr, \"mychannel\", nodeID) {\n    return fmt.Errorf(\"node %d is not in mychannel's membership\", nodeID)\n}","typeGuard":"func nodeExists(mgr *cluster.AuthCommMgr, channel string, id uint64) bool {\n    mgr.Lock.RLock()\n    defer mgr.Lock.RUnlock()\n    return mgr.Chan2Members[channel].ByID(id) != nil\n}","tryCatchPattern":"rc, err := comm.Remote(channel, id)\nif err != nil {\n    if strings.Contains(err.Error(), \"doesn't exist in channel\") {\n        // stale/invalid node ID: refresh membership from channel config and re-resolve\n        comm.Configure(channel, fetchCurrentMembers(channel))\n        rc, err = comm.Remote(channel, id)\n    }\n    return err\n}","preventionTips":["Re-resolve node IDs from current channel config after every reconfiguration; never cache consenter IDs long-term.","Validate target node IDs against the channel's consenter set before calling Remote().","Check channel config sequence changes on the remote before reusing previously resolved stubs.","Log current membership when this error occurs to detect membership drift quickly."],"tags":["hyperledger-fabric","orderer","consenter","membership"],"backgroundTag":"node-not-in-channel-membership","analyzedSha":"2736b63f8fd5932511d56fe68b7039d15977f7f6","analyzedAt":"2026-09-04T08:52:36.465Z","contentChangedAt":"2026-09-04T08:52:36.465Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}