hyperledger/fabric · error

Message is neither a Submit nor Consensus request

Error message

Message is neither a Submit nor Consensus request

What it means

handleMessage inspects the received clusterRequest's Type. Valid requests are either a Submit request (forwarded to RequestHandler.OnSubmit) or a Consensus request (forwarded to RequestHandler.OnConsensus). Any other message type reaching this point is a protocol violation — the auth envelope carried a message the cluster Step service cannot dispatch — so the stream errors with 'Message is neither a Submit nor Consensus request'.

Source

Thrown at orderer/common/cluster/clusterservice.go:226

	exp.checkExpiration(time.Now(), channel)

	if tranReq := request.GetNodeTranrequest(); tranReq != nil {
		submitReq := &orderer.SubmitRequest{
			Channel:           channel,
			LastValidationSeq: tranReq.LastValidationSeq,
			Payload:           tranReq.Payload,
		}
		return s.RequestHandler.OnSubmit(channel, sender, submitReq)
	} else if clusterConReq := request.GetNodeConrequest(); clusterConReq != nil {
		conReq := &orderer.ConsensusRequest{
			Channel:  channel,
			Payload:  clusterConReq.Payload,
			Metadata: clusterConReq.Metadata,
		}
		return s.RequestHandler.OnConsensus(channel, sender, conReq)
	}
	return errors.Errorf("Message is neither a Submit nor Consensus request")
}

func (s *ClusterService) initializeExpirationCheck(stream orderer.ClusterNodeService_StepServer, endpoint, nodeName string) *certificateExpirationCheck {
	expiresAt := time.Time{}
	cert := util.ExtractCertificateFromContext(stream.Context())
	if cert != nil {
		expiresAt = cert.NotAfter
	}

	return &certificateExpirationCheck{
		minimumExpirationWarningInterval: s.MinimumExpirationWarningInterval,
		expirationWarningThreshold:       s.CertExpWarningThreshold,
		expiresAt:                        expiresAt,
		endpoint:                         endpoint,
		nodeName:                         nodeName,
		alert: func(template string, args ...any) {
			s.Logger.Warningf(template, args...)
		},

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Align all orderers on the same Fabric version so the Step request types are understood on both ends.
  2. On the sending side, ensure only cluster.Step requests built via the cluster RPC (Submit via Broadcast-style forwarding, Consensus via etcdraft) are sent to the cluster port — not Deliver/Broadcast envelopes.
  3. Inspect the incoming message with StepLogger debug to identify the unexpected Type and which sender produced it.
  4. Check for intermediaries or custom code that re-wraps or re-marshals the StepRequest payload and remove that behavior.
  5. If a custom client is at fault, regenerate the request using the fabric-protos orderer.ClusterNodeService definitions.

Example fix

// before (custom client sends a Broadcast envelope to the cluster Step endpoint)
req := &orderer.BroadcastRequest{...}
stepClient.Send(req)
// after — send the proper cluster request type
req := &orderer.StepRequest{
    Payload: &orderer.StepRequest_SubmitRequest{SubmitRequest: submitReq},
}
stepClient.Send(req)
Defensive patterns

Strategy: validation

Validate before calling

// Before dialing the cluster port, assert the request type is dispatchable
switch r := stepReq.Payload.(type) {
case *orderer.StepRequest_SubmitRequest:
    // ok
case *orderer.StepRequest_ConsensusRequest:
    // ok
default:
    return fmt.Errorf("refusing to send unsupported StepRequest payload %T over cluster port", r)
}

Type guard

func isDispatchableStepRequest(p *orderer.StepRequest) bool {
    switch p.Payload.(type) {
    case *orderer.StepRequest_SubmitRequest, *orderer.StepRequest_ConsensusRequest:
        return true
    }
    return false
}

Try / catch

if err := handleMessage(...); err != nil && strings.Contains(err.Error(), "neither a Submit nor Consensus") {
    log.Printf("unsupported cluster message from %s; dropping stream", addr)
    stream.CloseSend()
}

Prevention

When it happens

Trigger: A Step message arrives whose inner clusterRequest type is neither Submit nor Consensus — e.g. a client sends a mis-constructed orderer.StepRequest, an envelope's payload was wrapped/typed incorrectly, or a version-skewed node sends a type this build doesn't recognize.

Common situations: Mixed Fabric versions where the wire format or request types changed; a custom/gRPC client hand-crafting Step messages; corrupted or re-wrapped envelopes produced by intermediate proxies; a sender accidentally using the peer-facing broadcast/deliver payload format against the orderer cluster port.

Related errors


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