hyperledger/fabric · error

ErrChannelNotReady

ErrChannelNotReady

Error message

channel is not ready, he is a follower

What it means

ErrChannelNotReady is returned by the channel participation API when an update is attempted on a channel whose local node is a follower in the consortium rather than a fully-started (active) participant. In Hyperledger Fabric's channel participation, only channels in the 'active' state can accept configuration updates via the REST API; follower channels are passively replicating and reject mutations. The error surfaces as HTTP 403 Forbidden from the UpdateChannel REST handler.

Source

Thrown at orderer/common/types/errors.go:37

// ErrChannelAlreadyExists is returned when trying to join a app channel that already exists (when the system channel does not
// exist), or when trying to join the system channel when it already exists.
var ErrChannelAlreadyExists = errors.New("channel already exists")

// ErrAppChannelsAlreadyExists is returned when trying to join a system channel (that does not exist) when application channels
// already exist.
var ErrAppChannelsAlreadyExists = errors.New("application channels already exist")

// ErrChannelNotExist is returned when trying to remove or list a channel that does not exist
var ErrChannelNotExist = errors.New("channel does not exist")

// ErrChannelPendingRemoval is returned when trying to remove or list a channel that is being removed.
var ErrChannelPendingRemoval = errors.New("channel pending removal")

// ErrChannelRemovalFailure is returned when a removal attempt failure has been recorded.
var ErrChannelRemovalFailure = errors.New("channel removal failure")

// ErrChannelNotReady is returned when trying to update a channel that is a follower
var ErrChannelNotReady = errors.New("channel is not ready, he is a follower")

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Wait until the channel status becomes 'active' (check GET /participation/v1/channels/{channelID}) before issuing the update.
  2. Verify the node was properly added as a consenter and that the join (or snapshot restore) completed; re-join the channel if it is stuck in follower state.
  3. Ensure the config update is submitted to a node that is active in the channel, not a follower-only node.
  4. If the channel is pending removal or stuck, remove and re-join the channel via the participation API.

Example fix

// before: update immediately after join, channel still follower
info, err := manager.UpdateChannel(channelID, envelope)

// after: poll until active, then update
for {
    info, _ := manager.FetchChannel(channelID)
    if info.Status == types.StatusActive { break }
    time.Sleep(time.Second)
}
info, err := manager.UpdateChannel(channelID, envelope)
Defensive patterns

Strategy: validation

Validate before calling

info, err := manager.FetchChannel(channelID)
if err != nil { return err }
if info.Status != types.StatusActive {
    return fmt.Errorf("channel %s not active (status=%s), refusing update", channelID, info.Status)
}

Type guard

func channelReadyForUpdate(info types.ChannelInfo) bool {
    return info.Status == types.StatusActive
}

Prevention

When it happens

Trigger: Calling the channel participation REST API PUT /participation/v1/channels/{channelID} (UpdateChannel) when the channel's local state is 'follower' rather than 'active'. Also occurs in FetchBlock and sendUpdateError paths when the registrar reports the channel as a follower.

Common situations: An operator joins a channel with joinBySnapshot or as a follower before the node has caught up / been promoted to active, then tries to push a config update. Common after node restart before catch-up, or when updating a channel on a node that joined but never became a consenter/active member.

Related errors


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