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

  1. Verify connectivity and TLS settings to the orderer/peer (certs, host overrides)
  2. Retry fetching the block; deliver streams are often transiently interrupted
  3. Check server-side logs for why the stream was closed
  4. 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

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


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