hyperledger/fabric · error
chain is stopped
Error message
chain is stopped
What it means
WaitReady blocks until the chain can accept an operation by sending a nil onto submitC; if the chain has already stopped (doneC closed), the select picks doneC and returns 'chain is stopped'. Callers use it to wait for the chain to be ready to process requests, and this error tells them the chain is permanently halted.
Source
Thrown at orderer/consensus/etcdraft/chain.go:423
// Configure submits config type transactions for ordering.
func (c *Chain) Configure(env *common.Envelope, configSeq uint64) error {
c.Metrics.ConfigProposalsReceived.Add(1)
return c.Submit(&orderer.SubmitRequest{LastValidationSeq: configSeq, Payload: env, Channel: c.channelID}, 0)
}
// WaitReady blocks when the chain:
// - is catching up with other nodes using snapshot
//
// In any other case, it returns right away.
func (c *Chain) WaitReady() error {
if err := c.isRunning(); err != nil {
return err
}
select {
case c.submitC <- nil:
case <-c.doneC:
return errors.Errorf("chain is stopped")
}
return nil
}
// Errored returns a channel that closes when the chain stops.
func (c *Chain) Errored() <-chan struct{} {
c.errorCLock.RLock()
defer c.errorCLock.RUnlock()
return c.errorC
}
// Halt stops the chain.
func (c *Chain) Halt() {
c.stop()
}
func (c *Chain) stop() bool {View on GitHub (pinned to 2736b63f8f)
Solutions
- Detect the stopped chain and re-route submissions to another orderer in the consenter set.
- Check orderer logs for the reason the chain halted (e.g., 'Cowardly halting', channel removed) and fix the root cause.
- If the node's TLS/consenter certs were rotated, update the channel config and restart the orderer with correct certs so it can rejoin.
- If the channel was removed, re-join it via the participation API to restart the chain.
Defensive patterns
Strategy: try-catch
Try / catch
select {
case <-chain.Errored():
// chain stopped; route work to another orderer
return
default:
if err := chain.WaitReady(); err != nil {
if strings.Contains(err.Error(), "chain is stopped") {
failoverToAnotherOrderer()
}
}
} Prevention
- Check chain.Errored() before submitting during shutdown
- Handle halts (cert rotation, channel removal) promptly
- Load-balance submissions across multiple orderers
When it happens
Trigger: Calling Chain.WaitReady (e.g., before Submit on the broadcast/deliver path) after the raft chain has halted — due to fatal errors, being removed from the channel, config-driven halting, or Orderer shutdown.
Common situations: Clients submitting transactions while the orderer is shutting down; the node cowardly halting after detecting a wrong raft ID (out-of-date certificate); channel removal triggering chain stop while traffic is in flight.
Related errors
- unable to retrieve block [%d]
- failed to restore persisted raft data: %s
- failed to get last block
- chain is not started
- failed to process Raft Step message: %s
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/4c8a6d37cc671276.
Report an issue: GitHub.