hyperledger/fabric · error
got unexpected status: %v -- %s
Error message
got unexpected status: %v -- %s
What it means
getAck reads the broadcast stream response from the orderer; if the returned status is anything other than SUCCESS, it raises this error carrying the cb.Status enum and the orderer-provided info string. It means the orderer explicitly rejected the submitted envelope rather than a transport failure.
Source
Thrown at internal/peer/common/broadcastclient.go:44
oc, err := NewOrdererClientFromEnv()
if err != nil {
return nil, err
}
bc, err := oc.Broadcast()
if err != nil {
return nil, err
}
return &BroadcastGRPCClient{Client: bc}, nil
}
func (s *BroadcastGRPCClient) getAck() error {
msg, err := s.Client.Recv()
if err != nil {
return err
}
if msg.Status != cb.Status_SUCCESS {
return errors.Errorf("got unexpected status: %v -- %s", msg.Status, msg.Info)
}
return nil
}
// Send data to orderer
func (s *BroadcastGRPCClient) Send(env *cb.Envelope) error {
if err := s.Client.Send(env); err != nil {
return errors.WithMessage(err, "could not send to orderer node")
}
err := s.getAck()
return err
}
func (s *BroadcastGRPCClient) Close() error {
return s.Client.CloseSend()
}View on GitHub (pinned to 2736b63f8f)
Solutions
- Read the msg.Info text after the '--' for the orderer's specific rejection reason
- Check orderer logs (e.g. raft leader availability, channel existence) for the matching error
- If SERVICE_UNAVAILABLE, wait for/order the raft leader election to complete and retry
- If FORBIDDEN, fix the client's MSP/certificates so it has write access to the channel
- If BAD_REQUEST on channel update, re-validate the config update envelope against current config
Example fix
// before
err = broadcastClient.Send(env) // got unexpected status: SERVICE_UNAVAILABLE -- no leader
// after
// check orderer raft status first, then retry
if status == cb.Status_SERVICE_UNAVAILABLE { time.Sleep(2 * time.Second); err = broadcastClient.Send(env) } Defensive patterns
Strategy: retry
Validate before calling
// verify channel exists and client can write before sending
resp, err := cf.ChannelClient.GetChannelInfo()
if err != nil { return fmt.Errorf("channel %s not reachable: %w", channelID, err) } Type guard
func isOrdererStatusError(err error) bool {
return err != nil && strings.Contains(err.Error(), "got unexpected status:")
} Try / catch
if err := broadcastClient.Send(env); err != nil {
if strings.Contains(err.Error(), "SERVICE_UNAVAILABLE") {
return retryWithBackoff(func() error { return broadcastClient.Send(env) })
}
log.Errorf("orderer rejected envelope: %v", err) // inspect status + info after '--'
return err
} Prevention
- Monitor orderer raft leader availability before submitting transactions
- Confirm the client's MSP certs grant write access to the target channel
- Validate config update envelopes against current channel config before submitting
- Point the submit at an orderer that serves the target channel
When it happens
Trigger: Submitting a transaction/config envelope via BroadcastGRPCClient.Send and the orderer replies with a non-SUCCESS status such as BAD_REQUEST, FORBIDDEN, SERVICE_UNAVAILABLE, or NOT_READY, with msg.Info describing the cause.
Common situations: Orderer cluster has no leader (SERVICE_UNAVAILABLE); channel does not exist (BAD_REQUEST); the submitting client lacks write permission (FORBIDDEN); config update validation failure during channel update; submitting to wrong channel's orderer.
Related errors
- node id mismatch
- request message is nil
- Message is neither a Submit nor Consensus request
- badly formatted message, cannot extract channel
- channel %s doesn't exist
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/f197c8663bcf9a2f.
Report an issue: GitHub.