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
- Confirm client and server use matching fabric/protobuf versions
- Bypass proxies that may mangle the gRPC stream and connect directly
- Regenerate bindings from the correct protobuf definitions if customized
- 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
- Keep SDK/CLI and peer protobuf definitions in lockstep
- Avoid custom intermediaries on the deliver stream
- Log %T when unexpected payloads appear
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
- received unexpected response type (%T) from %s
- proto: Marshal called with nil
- error unmarshalling
- error encoding output
- error unmarshalling original config
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/12542b6e17216af2.
Report an issue: GitHub.