hyperledger/fabric · critical · ErrNotInChannel
not in the channel
Error message
not in the channel
What it means
ErrNotInChannel is a sentinel meaning the ordering node is not a member of the channel. It is returned by detectSelfID when the node's certificate cannot be found among the channel's consenters, and by IsChannelMember/IsConsensusOfChannel-style checks (TestChainParticipant flow), so callers like the etcdraft consenter can detect self-removal (eviction).
Source
Thrown at orderer/common/cluster/deliver.go:641
},
AtomicBroadcast_DeliverClient: stream,
}, nil
}
}
type errorAndResponse struct {
err error
resp *orderer.DeliverResponse
}
// ErrForbidden denotes that an ordering node refuses sending blocks due to access control.
var ErrForbidden = errors.New("forbidden pulling the channel")
// ErrServiceUnavailable denotes that an ordering node is not servicing at the moment.
var ErrServiceUnavailable = errors.New("service unavailable")
// ErrNotInChannel denotes that an ordering node is not in the channel
var ErrNotInChannel = errors.New("not in the channel")
var ErrRetryCountExhausted = errors.New("retry attempts exhausted")
View on GitHub (pinned to 2736b63f8f)
Solutions
- Fetch and inspect the latest config block to confirm whether the node's certificate is still in the consenter set
- If removal was unintended, re-add the node via a channel config update signed by sufficient admins
- If the node was legitimately evicted, stop its channel services or let the eviction suspicion mechanism halt the chain
- Verify local TLS/orderer certificates match what is registered in the channel config
Defensive patterns
Strategy: type-guard
Validate before calling
if !nodeCertInConfigBlock(localCert, latestConfigBlock) { return cluster.ErrNotInChannel } Type guard
func isNotInChannel(err error) bool { return errors.Is(err, cluster.ErrNotInChannel) } Try / catch
id, err := detectSelfID(puller)
if errors.Is(err, cluster.ErrNotInChannel) {
// local node evicted: halt chain / trigger eviction suspicion
return haltConsensus()
} Prevention
- Diff the node's TLS cert against the consenter set after every config update
- Handle ErrNotInChannel explicitly to self-halt when evicted
- Keep certificate rotation coordinated with channel config updates
- Verify channel names when constructing pullers
When it happens
Trigger: detectSelfID scans all consenters in the latest config block and finds no certificate matching the local node (consenter.go:115); TestChainParticipant returns it when probing reveals the node is not authorized; IsConsenterOfChannel fails to match the local cert.
Common situations: Node was voted out / removed from the consenter set via config update (Raft eviction); certificate rotation left stale certs in local config; channel name typo causing lookup against the wrong channel's consenter set.
Related errors
- faulty node, received: %v
- response is of type %v, but expected a block
- retry attempts exhausted
- stream %d aborted
- failed to process Raft Step message: %s
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/6a4b0d5b61e47b98.
Report an issue: GitHub.