hyperledger/fabric · error
faulty node, received: %v
Error message
faulty node, received: %v
What it means
extractBlockFromResponse in the cluster BlockPuller returns this when an ordering node's Deliver response is neither a block nor a recognized error status — the response status is something other than SUCCESS, FORBIDDEN, or SERVICE_UNAVAILABLE. It signals the node misbehaved or the channel/TLS state is broken, and the puller will treat the endpoint as faulty and fail over to another one.
Source
Thrown at orderer/common/cluster/deliver.go:478
}
if block.Data == nil {
return nil, errors.New("block data is nil")
}
if block.Header == nil {
return nil, errors.New("block header is nil")
}
if block.Metadata == nil || len(block.Metadata.Metadata) == 0 {
return nil, errors.New("block metadata is empty")
}
return block, nil
case *orderer.DeliverResponse_Status:
if t.Status == common.Status_FORBIDDEN {
return nil, ErrForbidden
}
if t.Status == common.Status_SERVICE_UNAVAILABLE {
return nil, ErrServiceUnavailable
}
return nil, errors.Errorf("faulty node, received: %v", resp)
default:
return nil, errors.Errorf("response is of type %v, but expected a block", reflect.TypeOf(resp.Type))
}
}
func (p *BlockPuller) seekLastEnvelope() (*common.Envelope, error) {
return protoutil.CreateSignedEnvelopeWithTLSBinding(
common.HeaderType_DELIVER_SEEK_INFO,
p.Channel,
p.Signer,
last(),
int32(0),
uint64(0),
util.ComputeSHA256(p.TLSCert),
)
}
func (p *BlockPuller) seekNextEnvelope(startSeq uint64) (*common.Envelope, error) {View on GitHub (pinned to 2736b63f8f)
Solutions
- Verify all ordering nodes run compatible Fabric versions and share the channel configuration
- Check the remote node's logs for why the deliver request was rejected (status logged in the response)
- Confirm mutual TLS certificates and TLSRootCAs are correctly configured for the cluster connection
- Ensure the pulling node is actually a member of the channel with a valid identity
Defensive patterns
Strategy: retry
Validate before calling
if resp.GetType() != orderer.DeliverResponse_BLOCK { return fmt.Errorf("non-block response type: %v", resp.Type) } Type guard
func isBlockResponse(resp *orderer.DeliverResponse) bool { return resp != nil && resp.GetType() == orderer.DeliverResponse_BLOCK } Try / catch
resp, err := puller.PullBlock(seq)
if err != nil {
if errors.Is(err, cluster.ErrForbidden) || errors.Is(err, cluster.ErrServiceUnavailable) {
// fail over / retry another endpoint
}
return err
} Prevention
- Keep Fabric versions aligned across ordering nodes
- Maintain correct mutual TLS and root CA configuration
- Ensure cluster endpoints point at current channel consenters
- Monitor orderer logs for non-SUCCESS deliver statuses
When it happens
Trigger: A DeliverResponse arrives with a Status other than common.Status_SUCCESS, Status_FORBIDDEN, or Status_SERVICE_UNAVAILABLE (e.g. BAD_REQUEST from an incompatible SeekInfo, or a node rejecting the seek); any non-DeliverResponse shape reaching the extractor.
Common situations: Fabric version mismatch between the pulling orderer and the remote ordering node; a consenter removed from the channel still listed in the cluster configuration; misconfigured mutual TLS causing the remote node to reject the deliver seek; pointing the puller at a non-orderer gRPC endpoint.
Related errors
- not in the channel
- response is of type %v, but expected a block
- retry attempts exhausted
- stream %d aborted
- failed to process Raft Step message: %s
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/3d5141f0bd000521.
Report an issue: GitHub.