hyperledger/fabric · error

response error: unknown type %T

Error message

response error: unknown type %T

What it means

readBlock's type switch on the DeliverResponse oneof matched neither Status nor Block, meaning the response carried an unexpected payload type. This is a protocol-shape mismatch rather than a server rejection.

Source

Thrown at internal/peer/common/deliverclient.go:86

	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)
	}
}

// GetSpecifiedBlock gets the specified block from a peer/orderer's deliver
// service
func (d *DeliverClient) GetSpecifiedBlock(num uint64) (*cb.Block, error) {
	err := d.seekSpecified(num)
	if err != nil {
		return nil, errors.WithMessage(err, "error getting specified block")
	}

	return d.readBlock()
}

// GetOldestBlock gets the oldest block from a peer/orderer's deliver service
func (d *DeliverClient) GetOldestBlock() (*cb.Block, error) {
	err := d.seekOldest()
	if err != nil {

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Confirm client and server use matching fabric/protobuf versions
  2. Bypass proxies that may mangle the gRPC stream and connect directly
  3. Regenerate bindings from the correct protobuf definitions if customized
  4. Log the full message type for diagnosis before retrying

Example fix

// before
switch t := msg.Type.(type) {
case *ab.DeliverResponse_Block: ...
}
// after
switch t := msg.Type.(type) {
case *ab.DeliverResponse_Block: ...
case *ab.DeliverResponse_Status: handleStatus(t)
default: return nil, errors.Errorf("response error: unknown type %T", t)
}
Defensive patterns

Strategy: type-guard

Validate before calling

// ensure client and server protobuf versions match before opening the stream
// fabric-sdk version must match the peer/orderer release line

Type guard

block, ok := msg.Type.(*ab.DeliverResponse_Block)
if !ok {
    return fmt.Errorf("expected block response, got %T", msg.Type)
}

Try / catch

block, err := client.GetSpecifiedBlock(num)
if err != nil && strings.Contains(err.Error(), "unknown type") {
    log.Printf("protocol mismatch: %v; verify fabric versions", err)
}

Prevention

When it happens

Trigger: The deliver stream delivered a DeliverResponse whose oneof is neither DeliverResponse_Status nor DeliverResponse_Block — practically only from a malformed or non-standard server implementation.

Common situations: Version-skewed server/client protobuf definitions, a custom or intermediary gRPC service speaking a different message shape, corrupted stream framing.

Related errors


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