hyperledger/fabric · warning

chain is not started

Error message

chain is not started

What it means

isRunning is a precondition check used by Step/Submit-style entry points. It performs a non-blocking receive on startC: if the chain's Start has not yet run, it returns 'chain is not started'. This prevents interacting with the raft node before it exists.

Source

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

		c.statusReportMutex.Lock()
		defer c.statusReportMutex.Unlock()

		// If the haltCallback registers the chain in to the inactive chain registry (i.e., system channel exists) then
		// this is the correct consensusRelation. If the haltCallback transfers responsibility to a follower.Chain, then
		// this chain is about to be GC anyway. The new follower.Chain replacing this one will report the correct
		// StatusReport.
		c.consensusRelation = types.ConsensusRelationConfigTracker
	}

	// active nodes metric shouldn't be frozen once a channel is stopped.
	c.Metrics.ActiveNodes.Set(float64(0))
}

func (c *Chain) isRunning() error {
	select {
	case <-c.startC:
	default:
		return errors.Errorf("chain is not started")
	}

	select {
	case <-c.doneC:
		return errors.Errorf("chain is stopped")
	default:
	}

	return nil
}

// Consensus passes the given ConsensusRequest message to the raft.Node instance
func (c *Chain) Consensus(req *orderer.ConsensusRequest, sender uint64) error {
	if err := c.isRunning(); err != nil {
		return err
	}

	stepMsg := &raftpb.Message{}

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Retry after a short delay — this is a transient startup race; the chain will start momentarily.
  2. Verify chain start-up is not blocked by earlier errors in the orderer log (WAL restore, storage creation) that leave the chain never-started.
  3. Ensure the orderer joined the channel properly so Start() is invoked; a channel registered but never started indicates a lifecycle bug or failed creation.
  4. If persistent, restart the orderer and check for errors preventing the raft chain from starting.
Defensive patterns

Strategy: retry

Try / catch

if err := chain.WaitReady(); err != nil {
    if strings.Contains(err.Error(), "chain is not started") {
        time.Sleep(100 * time.Millisecond)
        return chain.WaitReady() // transient startup race
    }
    return err
}

Prevention

When it happens

Trigger: Calling Chain.Step (consensus message handling) or Submit before the chain's Start() go-routine has initialized submitC/startC — e.g., consensus messages arriving from other orderers immediately after chain registration but before start completes.

Common situations: A burst of raft Step messages arriving from peers at exactly chain-creation time; onboarding a channel while other orderers already gossip consensus messages; races during dynamic channel creation.

Related errors


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