hyperledger/fabric · error
error receiving
Error message
error receiving
What it means
readBlock blocks on the deliver gRPC stream; Recv returned a transport error, which is wrapped with "error receiving". The client never received a deliver response (status or block) because the stream broke or the server closed it.
Source
Thrown at internal/peer/common/deliverclient.go:70
}
env := seekHelper(d.ChannelID, seekPosition, d.TLSCertHash, d.Signer, d.BestEffort)
return d.Service.Send(env)
}
func (d *DeliverClient) seekOldest() error {
env := seekHelper(d.ChannelID, seekOldest, d.TLSCertHash, d.Signer, d.BestEffort)
return d.Service.Send(env)
}
func (d *DeliverClient) seekNewest() error {
env := seekHelper(d.ChannelID, seekNewest, d.TLSCertHash, d.Signer, d.BestEffort)
return d.Service.Send(env)
}
func (d *DeliverClient) readBlock() (*cb.Block, error) {
msg, err := d.Service.Recv()
if err != nil {
return nil, errors.Wrap(err, "error receiving")
}
switch t := msg.Type.(type) {
case *ab.DeliverResponse_Status:
logger.Infof("Expect block, but got status: %v", t)
return nil, errors.Errorf("can't read the block: %v", t)
case *ab.DeliverResponse_Block:
logger.Infof("Received block: %v", t.Block.Header.Number)
if resp, err := d.Service.Recv(); err != nil { // Flush the success message
logger.Errorf("Failed to flush success message: %s", err)
} else if status := resp.GetStatus(); status != cb.Status_SUCCESS {
logger.Errorf("Expect status to be SUCCESS, got: %s", status)
}
return t.Block, nil
default:
return nil, errors.Errorf("response error: unknown type %T", t)
}
}View on GitHub (pinned to 2736b63f8f)
Solutions
- Verify connectivity and TLS settings to the orderer/peer (certs, host overrides)
- Retry fetching the block; deliver streams are often transiently interrupted
- Check server-side logs for why the stream was closed
- Increase timeouts and ensure the deliver envelope was accepted (Send succeeded) before Recv
Example fix
// before
block, err := deliverClient.GetNewestBlock()
// after
block, err := deliverClient.GetNewestBlock()
if err != nil && strings.Contains(err.Error(), "error receiving") { block, err = retryFetch() } Defensive patterns
Strategy: retry
Validate before calling
// pre-check connectivity
conn, err := grpc.DialContext(ctx, addr, grpc.WithTransportCredentials(creds), grpc.WithBlock())
if err != nil { return fmt.Errorf("orderer/peer unreachable: %w", err) } Try / catch
block, err := client.GetNewestBlock()
if err != nil {
if strings.Contains(err.Error(), "error receiving") {
time.Sleep(backoff)
block, err = client.GetNewestBlock()
}
} Prevention
- Enable gRPC keepalives for long-lived deliver streams
- Validate TLS certs and host overrides up front
- Set sane deadlines and retry with backoff
When it happens
Trigger: d.Service.Recv() on the atomic broadcast/deliver stream fails — connection dropped, TLS handshake failure, context timeout/cancellation, or server closed the stream.
Common situations: Orderer/peer unreachable mid-stream, idle connections killed by a proxy, TLS cert mismatch, or deliver request rejected leading to stream teardown.
Related errors
- error receiving from peer deliver service
- message is nil
- context finished before block retrieved
- orderer `%s` hung up without sending status
- cannot find ledger for channel %s
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/9e14c3a98176ba0f.
Report an issue: GitHub.