hyperledger/fabric · error
message is neither a Submit nor a Consensus request
Error message
message is neither a Submit nor a Consensus request
What it means
The cluster Step service's handleMessage expects every incoming request on the stream to be either a SubmitRequest (forwarded transactions) or a ConsensusRequest (Raft messages); anything else produces this error and aborts handling. It guards the Step RPC against malformed or unsupported message types.
Source
Thrown at orderer/common/cluster/service.go:98
return err
}
exp.checkExpiration(time.Now(), extractChannel(request))
if s.StepLogger.IsEnabledFor(zap.DebugLevel) {
nodeName := commonNameFromContext(stream.Context())
s.StepLogger.Debugf("Received message from %s(%s): %v", nodeName, addr, requestAsString(request))
}
if submitReq := request.GetSubmitRequest(); submitReq != nil {
nodeName := commonNameFromContext(stream.Context())
s.Logger.Debugf("Received message from %s(%s): %v", nodeName, addr, requestAsString(request))
return s.handleSubmit(submitReq, stream, addr)
} else if consensusReq := request.GetConsensusRequest(); consensusReq != nil {
return s.Dispatcher.DispatchConsensus(stream.Context(), request.GetConsensusRequest())
}
return errors.Errorf("message is neither a Submit nor a Consensus request")
}
func (s *Service) handleSubmit(request *orderer.SubmitRequest, stream StepStream, addr string) error {
err := s.Dispatcher.DispatchSubmit(stream.Context(), request)
if err != nil {
s.Logger.Warningf("Handling of Submit() from %s failed: %v", addr, err)
return err
}
return err
}
func (s *Service) initializeExpirationCheck(stream orderer.Cluster_StepServer, endpoint, nodeName string) *certificateExpirationCheck {
return &certificateExpirationCheck{
minimumExpirationWarningInterval: s.MinimumExpirationWarningInterval,
expirationWarningThreshold: s.CertExpWarningThreshold,
expiresAt: expiresAt(stream),
endpoint: endpoint,
nodeName: nodeName,View on GitHub (pinned to 2736b63f8f)
Solutions
- Ensure all ordering nodes run the same compatible Fabric version
- Check what client/peer is sending the malformed Step requests in the logs (addr is logged) and fix or upgrade it
- Verify no intermediate proxy is corrupting or rewriting gRPC streams
- Confirm applications use Broadcast/Deliver APIs, not raw Step, for transaction submission
Defensive patterns
Strategy: validation
Validate before calling
switch {
case req.GetSubmitRequest() != nil: // Submit path
case req.GetConsensusRequest() != nil: // Consensus path
default:
return errors.New("message is neither a Submit nor a Consensus request")
} Type guard
func isKnownClusterRequest(req *orderer.Request) bool {
return req.GetSubmitRequest() != nil || req.GetConsensusRequest() != nil
} Try / catch
err := service.Step(stream, request)
if err != nil && strings.Contains(err.Error(), "neither a Submit nor a Consensus request") {
// sender sends unsupported type: log addr, drop or close stream
return stream.Close()
} Prevention
- Run identical Fabric versions on all cluster members
- Only call Step via the built-in cluster/etcdraft plumbing
- Keep load balancers gRPC-stream-transparent
- Validate request payloads before sending on the Step stream
When it happens
Trigger: A client sends a StepRequest whose inner request has neither SubmitRequest nor ConsensusRequest populated; a Fabric client of a different version sends an unexpected message type over the cluster Step stream.
Common situations: Fabric version incompatibility between ordering nodes (new message types unknown to the receiver); a misbehaving or buggy custom client calling Step directly; corrupted gRPC payloads after proxy/LB interference with streaming.
Related errors
- invalid request object
- Message is neither a Submit nor Consensus request
- connection to %d(%s) is in state %s
- service stream returned with invalid response type
- response is of type %v, but expected a block
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/cb8cf3ad1ed99a38.
Report an issue: GitHub.